├── .gitignore ├── .travis.yml ├── .yardopts ├── .yardopts_guide ├── CHANGELOG.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── appveyor.yml ├── axlsx.gemspec ├── examples ├── 2010_comments.rb ├── anchor_swapping.rb ├── auto_filter.rb ├── basic_charts.rb ├── chart_colors.rb ├── colored_links.rb ├── conditional_formatting │ ├── example_conditional_formatting.rb │ ├── getting_barred.rb │ ├── hitting_the_high_notes.rb │ ├── scaled_colors.rb │ └── stop_and_go.rb ├── data_validation.rb ├── example.rb ├── extractive.rb ├── image1.gif ├── image1.jpeg ├── image1.jpg ├── image1.png ├── image1_fake.jpg ├── ios_preview.rb ├── merge_cells.rb ├── no_grid_with_borders.rb ├── page_setup.rb ├── pivot_table.rb ├── pivot_test.rb ├── sample.png ├── sheet_protection.rb ├── skydrive │ └── real_example.rb ├── split.rb ├── styles.rb ├── underline.rb └── wrap_text.rb ├── lib ├── axlsx.rb ├── axlsx │ ├── content_type │ │ ├── abstract_content_type.rb │ │ ├── content_type.rb │ │ ├── default.rb │ │ └── override.rb │ ├── doc_props │ │ ├── app.rb │ │ └── core.rb │ ├── drawing │ │ ├── area_chart.rb │ │ ├── area_series.rb │ │ ├── ax_data_source.rb │ │ ├── axes.rb │ │ ├── axis.rb │ │ ├── bar_3D_chart.rb │ │ ├── bar_chart.rb │ │ ├── bar_series.rb │ │ ├── bubble_chart.rb │ │ ├── bubble_series.rb │ │ ├── cat_axis.rb │ │ ├── chart.rb │ │ ├── d_lbls.rb │ │ ├── drawing.rb │ │ ├── graphic_frame.rb │ │ ├── hyperlink.rb │ │ ├── line_3D_chart.rb │ │ ├── line_chart.rb │ │ ├── line_series.rb │ │ ├── marker.rb │ │ ├── num_data.rb │ │ ├── num_data_source.rb │ │ ├── num_val.rb │ │ ├── one_cell_anchor.rb │ │ ├── pic.rb │ │ ├── picture_locking.rb │ │ ├── pie_3D_chart.rb │ │ ├── pie_series.rb │ │ ├── scaling.rb │ │ ├── scatter_chart.rb │ │ ├── scatter_series.rb │ │ ├── ser_axis.rb │ │ ├── series.rb │ │ ├── series_title.rb │ │ ├── str_data.rb │ │ ├── str_val.rb │ │ ├── title.rb │ │ ├── two_cell_anchor.rb │ │ ├── val_axis.rb │ │ ├── view_3D.rb │ │ ├── vml_drawing.rb │ │ └── vml_shape.rb │ ├── package.rb │ ├── rels │ │ ├── relationship.rb │ │ └── relationships.rb │ ├── stylesheet │ │ ├── border.rb │ │ ├── border_pr.rb │ │ ├── cell_alignment.rb │ │ ├── cell_protection.rb │ │ ├── cell_style.rb │ │ ├── color.rb │ │ ├── dxf.rb │ │ ├── fill.rb │ │ ├── font.rb │ │ ├── gradient_fill.rb │ │ ├── gradient_stop.rb │ │ ├── num_fmt.rb │ │ ├── pattern_fill.rb │ │ ├── styles.rb │ │ ├── table_style.rb │ │ ├── table_style_element.rb │ │ ├── table_styles.rb │ │ └── xf.rb │ ├── util │ │ ├── accessors.rb │ │ ├── constants.rb │ │ ├── mime_type_utils.rb │ │ ├── options_parser.rb │ │ ├── parser.rb │ │ ├── serialized_attributes.rb │ │ ├── simple_typed_list.rb │ │ ├── storage.rb │ │ └── validators.rb │ ├── version.rb │ └── workbook │ │ ├── defined_name.rb │ │ ├── defined_names.rb │ │ ├── shared_strings_table.rb │ │ ├── workbook.rb │ │ ├── workbook_view.rb │ │ ├── workbook_views.rb │ │ └── worksheet │ │ ├── auto_filter │ │ ├── auto_filter.rb │ │ ├── filter_column.rb │ │ └── filters.rb │ │ ├── break.rb │ │ ├── cell.rb │ │ ├── cell_serializer.rb │ │ ├── cfvo.rb │ │ ├── cfvos.rb │ │ ├── col.rb │ │ ├── col_breaks.rb │ │ ├── color_scale.rb │ │ ├── cols.rb │ │ ├── comment.rb │ │ ├── comments.rb │ │ ├── conditional_formatting.rb │ │ ├── conditional_formatting_rule.rb │ │ ├── conditional_formattings.rb │ │ ├── data_bar.rb │ │ ├── data_validation.rb │ │ ├── data_validations.rb │ │ ├── date_time_converter.rb │ │ ├── dimension.rb │ │ ├── header_footer.rb │ │ ├── icon_set.rb │ │ ├── merged_cells.rb │ │ ├── outline_pr.rb │ │ ├── page_margins.rb │ │ ├── page_set_up_pr.rb │ │ ├── page_setup.rb │ │ ├── pane.rb │ │ ├── pivot_table.rb │ │ ├── pivot_table_cache_definition.rb │ │ ├── pivot_tables.rb │ │ ├── print_options.rb │ │ ├── protected_range.rb │ │ ├── protected_ranges.rb │ │ ├── rich_text.rb │ │ ├── rich_text_run.rb │ │ ├── row.rb │ │ ├── row_breaks.rb │ │ ├── selection.rb │ │ ├── sheet_calc_pr.rb │ │ ├── sheet_data.rb │ │ ├── sheet_format_pr.rb │ │ ├── sheet_pr.rb │ │ ├── sheet_protection.rb │ │ ├── sheet_view.rb │ │ ├── table.rb │ │ ├── table_style_info.rb │ │ ├── tables.rb │ │ ├── worksheet.rb │ │ ├── worksheet_comments.rb │ │ ├── worksheet_drawing.rb │ │ ├── worksheet_hyperlink.rb │ │ └── worksheet_hyperlinks.rb └── schema │ ├── dc.xsd │ ├── dcmitype.xsd │ ├── dcterms.xsd │ ├── dml-chart.xsd │ ├── dml-chartDrawing.xsd │ ├── dml-compatibility.xsd │ ├── dml-diagram.xsd │ ├── dml-lockedCanvas.xsd │ ├── dml-main.xsd │ ├── dml-picture.xsd │ ├── dml-spreadsheetDrawing.xsd │ ├── dml-wordprocessingDrawing.xsd │ ├── opc-contentTypes.xsd │ ├── opc-coreProperties.xsd │ ├── opc-digSig.xsd │ ├── opc-relationships.xsd │ ├── pml.xsd │ ├── shared-additionalCharacteristics.xsd │ ├── shared-bibliography.xsd │ ├── shared-commonSimpleTypes.xsd │ ├── shared-customXmlDataProperties.xsd │ ├── shared-customXmlSchemaProperties.xsd │ ├── shared-documentPropertiesCustom.xsd │ ├── shared-documentPropertiesExtended.xsd │ ├── shared-documentPropertiesVariantTypes.xsd │ ├── shared-math.xsd │ ├── shared-relationshipReference.xsd │ ├── sml.xsd │ ├── vml-main.xsd │ ├── vml-officeDrawing.xsd │ ├── vml-presentationDrawing.xsd │ ├── vml-spreadsheetDrawing.xsd │ ├── vml-wordprocessingDrawing.xsd │ ├── wml.xsd │ └── xml.xsd ├── notes_on_header_footer.md ├── rubima.md └── test ├── benchmark.rb ├── content_type ├── tc_content_type.rb ├── tc_default.rb └── tc_override.rb ├── doc_props ├── tc_app.rb └── tc_core.rb ├── drawing ├── tc_area_chart.rb ├── tc_area_series.rb ├── tc_axes.rb ├── tc_axis.rb ├── tc_bar_3D_chart.rb ├── tc_bar_chart.rb ├── tc_bar_series.rb ├── tc_bubble_chart.rb ├── tc_bubble_series.rb ├── tc_cat_axis.rb ├── tc_cat_axis_data.rb ├── tc_chart.rb ├── tc_d_lbls.rb ├── tc_data_source.rb ├── tc_drawing.rb ├── tc_graphic_frame.rb ├── tc_hyperlink.rb ├── tc_line_3d_chart.rb ├── tc_line_chart.rb ├── tc_line_series.rb ├── tc_marker.rb ├── tc_named_axis_data.rb ├── tc_num_data.rb ├── tc_num_val.rb ├── tc_one_cell_anchor.rb ├── tc_pic.rb ├── tc_picture_locking.rb ├── tc_pie_3D_chart.rb ├── tc_pie_series.rb ├── tc_scaling.rb ├── tc_scatter_chart.rb ├── tc_scatter_series.rb ├── tc_ser_axis.rb ├── tc_series.rb ├── tc_series_title.rb ├── tc_str_data.rb ├── tc_str_val.rb ├── tc_title.rb ├── tc_two_cell_anchor.rb ├── tc_val_axis.rb ├── tc_view_3D.rb ├── tc_vml_drawing.rb └── tc_vml_shape.rb ├── profile.rb ├── rels ├── tc_relationship.rb └── tc_relationships.rb ├── stylesheet ├── tc_border.rb ├── tc_border_pr.rb ├── tc_cell_alignment.rb ├── tc_cell_protection.rb ├── tc_cell_style.rb ├── tc_color.rb ├── tc_dxf.rb ├── tc_fill.rb ├── tc_font.rb ├── tc_gradient_fill.rb ├── tc_gradient_stop.rb ├── tc_num_fmt.rb ├── tc_pattern_fill.rb ├── tc_styles.rb ├── tc_table_style.rb ├── tc_table_style_element.rb ├── tc_table_styles.rb └── tc_xf.rb ├── tc_axlsx.rb ├── tc_helper.rb ├── tc_package.rb ├── util ├── tc_mime_type_utils.rb ├── tc_serialized_attributes.rb ├── tc_simple_typed_list.rb └── tc_validators.rb └── workbook ├── tc_defined_name.rb ├── tc_shared_strings_table.rb ├── tc_workbook.rb ├── tc_workbook_view.rb └── worksheet ├── auto_filter ├── tc_auto_filter.rb ├── tc_filter_column.rb └── tc_filters.rb ├── tc_break.rb ├── tc_cell.rb ├── tc_cfvo.rb ├── tc_col.rb ├── tc_color_scale.rb ├── tc_comment.rb ├── tc_comments.rb ├── tc_conditional_formatting.rb ├── tc_data_bar.rb ├── tc_data_validation.rb ├── tc_date_time_converter.rb ├── tc_header_footer.rb ├── tc_icon_set.rb ├── tc_outline_pr.rb ├── tc_page_margins.rb ├── tc_page_set_up_pr.rb ├── tc_page_setup.rb ├── tc_pane.rb ├── tc_pivot_table.rb ├── tc_pivot_table_cache_definition.rb ├── tc_print_options.rb ├── tc_protected_range.rb ├── tc_rich_text.rb ├── tc_rich_text_run.rb ├── tc_row.rb ├── tc_selection.rb ├── tc_sheet_calc_pr.rb ├── tc_sheet_format_pr.rb ├── tc_sheet_pr.rb ├── tc_sheet_protection.rb ├── tc_sheet_view.rb ├── tc_table.rb ├── tc_table_style_info.rb ├── tc_worksheet.rb └── tc_worksheet_hyperlink.rb /.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | doc 3 | unzip 4 | coverage 5 | .yardoc 6 | coverage.data 7 | *.gem 8 | *.xlsx 9 | example.csv 10 | *.*~ 11 | .DS_Store 12 | tmp 13 | *.pem 14 | *.pfx 15 | examples/sprk2012 16 | .ruby-version 17 | .bundle/config 18 | .~lock* 19 | *.qcachegrind 20 | *.iml 21 | .idea -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | sudo: required 3 | dist: trusty 4 | group: beta 5 | cache: bundler 6 | bundler_args: --without profile 7 | 8 | notifications: 9 | irc: "irc.freenode.org#axlsx" 10 | email: 11 | recipients: 12 | - digital.ipseity@gmail.com 13 | on_success: always 14 | 15 | matrix: 16 | include: 17 | - rvm: 2.1 18 | - rvm: 2.2.8 19 | - rvm: 2.3.5 20 | - rvm: 2.4.2 21 | - rvm: rbx-3 22 | - rvm: jruby-19mode 23 | - rvm: jruby-9.1.17.0 24 | - rvm: ruby-head 25 | - rvm: jruby-head 26 | allow_failures: 27 | - rvm: rbx-3 28 | - rvm: ruby-head 29 | - rvm: jruby-9.1.17.0 30 | - rvm: jruby-head 31 | 32 | env: 33 | global: 34 | - JRUBY_OPTS="-Xcli.debug=true --debug" 35 | 36 | # https://github.com/jruby/jruby/wiki/FAQs#why-is-jruby-so-slow-to-install-via-rvm 37 | # https://docs.travis-ci.com/user/installing-dependencies#Installing-Packages-with-the-APT-Addon 38 | addons: 39 | apt: 40 | packages: 41 | - haveged 42 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --protected 2 | --no-private 3 | --title "AXLSX" 4 | --readme README.md 5 | --markup markdown 6 | --markup-provider kramdown 7 | - 8 | CHANGELOG.md 9 | LICENSE 10 | -------------------------------------------------------------------------------- /.yardopts_guide: -------------------------------------------------------------------------------- 1 | -t guide 2 | --title YARD 3 | -o doc_guide 4 | --exclude /server/templates/ 5 | --exclude /yard/rubygems/ 6 | --asset docs/images:images 7 | - 8 | docs/WhatsNew.md 9 | docs/GettingStarted.md 10 | docs/Overview.md 11 | docs/CodeObjects.md 12 | docs/Tags.md 13 | docs/Parser.md 14 | docs/Handlers.md 15 | docs/Templates.md 16 | docs/Glossary.md 17 | ChangeLog 18 | LICENSE 19 | LEGAL -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gemspec 3 | 4 | group :test do 5 | if RUBY_VERSION.to_i < 2 6 | gem 'rake', '>= 0.8.7', '< 11' 7 | gem 'json', '< 2' 8 | else 9 | gem 'rake' 10 | end 11 | gem 'simplecov', '>= 0.14.1' 12 | gem 'test-unit' 13 | end 14 | 15 | group :profile do 16 | gem 'ruby-prof', :platforms => :ruby 17 | end 18 | 19 | platforms :rbx do 20 | gem 'rubysl' 21 | gem 'rubysl-test-unit' 22 | gem 'racc' 23 | gem 'rubinius-coverage', '~> 2.0' 24 | end 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, 2012 Randy Morgan 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + '/lib/axlsx/version.rb') 2 | 3 | task :build => :gendoc do 4 | system "gem build axlsx.gemspec" 5 | end 6 | 7 | task :benchmark do 8 | require File.expand_path(File.dirname(__FILE__) + '/test/benchmark.rb') 9 | end 10 | 11 | task :gendoc do 12 | system "yardoc" 13 | system "yard stats --list-undoc" 14 | end 15 | 16 | 17 | require 'rake/testtask' 18 | Rake::TestTask.new do |t| 19 | t.libs << 'test' 20 | t.test_files = FileList['test/**/tc_*.rb'] 21 | t.verbose = false 22 | t.warning = true 23 | end 24 | 25 | task :release => :build do 26 | system "gem push axlsx-#{Axlsx::VERSION}.gem" 27 | end 28 | 29 | task :default => :test 30 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | version: 2.1.0.{build}-{branch} 2 | 3 | environment: 4 | matrix: 5 | - RUBY_VERSION: 23 6 | - RUBY_VERSION: 22 7 | - RUBY_VERSION: 21 8 | - RUBY_VERSION: 200 9 | - RUBY_VERSION: 193 10 | 11 | install: 12 | - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% 13 | - bundle install 14 | 15 | build: off 16 | 17 | before_test: 18 | - ruby -v 19 | - gem -v 20 | - bundle -v 21 | 22 | test_script: 23 | - bundle exec rake 24 | -------------------------------------------------------------------------------- /axlsx.gemspec: -------------------------------------------------------------------------------- 1 | require File.expand_path('../lib/axlsx/version', __FILE__) 2 | 3 | Gem::Specification.new do |s| 4 | s.name = 'axlsx' 5 | s.version = Axlsx::VERSION 6 | s.authors = ["Randy Morgan", "Jurriaan Pruis"] 7 | s.email = 'digital.ipseity@gmail.com' 8 | s.homepage = 'https://github.com/randym/axlsx' 9 | s.platform = Gem::Platform::RUBY 10 | s.date = Time.now.strftime('%Y-%m-%d') 11 | s.summary = "Excel OOXML (xlsx) with charts, styles, images and autowidth columns." 12 | s.has_rdoc = 'axlsx' 13 | s.license = 'MIT' 14 | s.description = <<-eof 15 | xlsx spreadsheet generation with charts, images, automated column width, customizable styles and full schema validation. Axlsx helps you create beautiful Office Open XML Spreadsheet documents ( Excel, Google Spreadsheets, Numbers, LibreOffice) 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. 16 | eof 17 | s.files = Dir.glob("{lib/**/*,examples/**/*.rb,examples/**/*.jpeg}") + %w{ LICENSE README.md Rakefile CHANGELOG.md .yardopts .yardopts_guide } 18 | s.test_files = Dir.glob("{test/**/*}") 19 | 20 | s.add_runtime_dependency 'nokogiri', '~> 1.8', '>= 1.8.2' 21 | s.add_runtime_dependency 'rubyzip','~> 1.2', '>= 1.2.1' 22 | s.add_runtime_dependency "htmlentities", "~> 4.3", '>= 4.3.4' 23 | s.add_runtime_dependency "mimemagic", '~> 0.3' 24 | 25 | s.add_development_dependency 'yard', "~> 0.9.8" 26 | s.add_development_dependency 'kramdown', '~> 1.16', '>= 1.16.2' 27 | s.add_development_dependency 'timecop', "~> 0.8.1" 28 | s.required_ruby_version = '>= 1.9.2' 29 | s.require_path = 'lib' 30 | end 31 | -------------------------------------------------------------------------------- /examples/2010_comments.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | 5 | #```ruby 6 | require 'axlsx' 7 | p = Axlsx::Package.new 8 | p.workbook.add_worksheet(:name => 'Excel 2010 comments') do |sheet| 9 | sheet.add_row ['Cell with visible comment'] 10 | sheet.add_row 11 | sheet.add_row 12 | sheet.add_row ['Cell with hidden comment'] 13 | 14 | sheet.add_comment :ref => 'A1', :author => 'XXX', :text => 'Visibile' 15 | sheet.add_comment :ref => 'A4', :author => 'XXX', :text => 'Hidden', :visible => false 16 | end 17 | p.serialize('excel_2010_comment_test.xlsx') 18 | -------------------------------------------------------------------------------- /examples/anchor_swapping.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 2 | require 'axlsx' 3 | xls = Axlsx::Package.new 4 | wb = xls.workbook 5 | wb.add_worksheet do |ws| 6 | img = File.expand_path('../image1.jpeg', __FILE__) 7 | ws.add_image(:image_src => img) do |image| 8 | image.start_at 2, 2 9 | image.end_at 5, 5 10 | end 11 | end 12 | wb.add_worksheet do |ws| 13 | img = File.expand_path('../image1.jpeg', __FILE__) 14 | ws.add_image(:image_src => img, :start_at => "B2") do |image| 15 | image.width = 70 16 | image.height = 50 17 | end 18 | end 19 | wb.add_worksheet do |ws| 20 | img = File.expand_path('../image1.jpeg', __FILE__) 21 | ws.add_image(:image_src => img, :start_at => [1,1]) do |image| 22 | image.end_at "E7" 23 | end 24 | end 25 | 26 | 27 | 28 | xls.serialize 'anchor.xlsx' 29 | -------------------------------------------------------------------------------- /examples/auto_filter.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | 4 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 5 | require 'axlsx' 6 | Axlsx::Package.new do |p| 7 | p.workbook.add_worksheet(:name => "Table") do |sheet| 8 | sheet.add_row ["Build Matrix"] 9 | sheet.add_row ["Build", "Duration", "Finished", "Rvm"] 10 | sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"] 11 | sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] 12 | sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] 13 | sheet.auto_filter = 'A2:D5' 14 | sheet.auto_filter.add_column 3, :filters, :filter_items => ['1.9.2'] 15 | end 16 | p.workbook.add_worksheet(:name => "Table 2") do |sheet| 17 | sheet.add_row ["Build Matrix"] 18 | sheet.add_row ["Build", "Duration", "Finished", "Rvm"] 19 | sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"] 20 | sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] 21 | sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] 22 | sheet.auto_filter = 'A2:D5' 23 | sheet.auto_filter.add_column 3, :filters, :filter_items => ['1.9.2'] 24 | end 25 | end.serialize('auto_filter.xlsx') 26 | -------------------------------------------------------------------------------- /examples/colored_links.rb: -------------------------------------------------------------------------------- 1 | require 'axlsx' 2 | 3 | ############################### 4 | # Function to output results data row to summary spreadsheet 5 | def outputRow (sid, type) 6 | 7 | $sumSheet.add_row [ sid, type, "1", "2", "3", "4", "5" ], :style => $black_cell 8 | 9 | if sid.odd? 10 | link = "A#{$curRow}" 11 | puts "outputRow: sid: #{sid}, link: #{link}" 12 | # Setting the style for the link will apply the xf that we created in the Main Program block 13 | $sumSheet[link].style = $blue_link 14 | $sumSheet.add_hyperlink :location => "'Log'!A#{$curRow}", :target => :sheet, :ref => link 15 | end 16 | $curRow += 1 17 | end 18 | 19 | ############################## 20 | # Main Program 21 | 22 | $package = Axlsx::Package.new 23 | $workbook = $package.workbook 24 | ## We want to create our sytles outside of the outputRow method 25 | # Each style only needs to be declared once in the workbook. 26 | $workbook.styles do |s| 27 | $black_cell = s.add_style :sz => 10, :alignment => { :horizontal=> :center } 28 | $blue_link = s.add_style :fg_color => '0000FF' 29 | end 30 | 31 | 32 | # Create summary sheet 33 | $sumSheet = $workbook.add_worksheet(:name => 'Summary') 34 | $sumSheet.add_row ["Test Results"], :sz => 16 35 | $sumSheet.add_row 36 | $sumSheet.add_row 37 | $sumSheet.add_row ["Note: Blue cells below are links to the Log sheet"], :sz => 10 38 | $sumSheet.add_row 39 | $workbook.styles do |s| 40 | black_cell = s.add_style :sz => 14, :alignment => { :horizontal=> :center } 41 | $sumSheet.add_row ["ID","Type","Match","Mismatch","Diffs","Errors","Result"], :style => black_cell 42 | end 43 | $sumSheet.column_widths 10, 10, 10, 11, 10, 10, 10 44 | 45 | # Starting data row in summary spreadsheet (after header info) 46 | $curRow = 7 47 | 48 | # Create Log Sheet 49 | $logSheet = $workbook.add_worksheet(:name => 'Log') 50 | $logSheet.column_widths 10 51 | $logSheet.add_row ['Log Detail'], :sz => 16 52 | $logSheet.add_row 53 | 54 | # Add rows to summary sheet 55 | for i in 1..10 do 56 | outputRow(i, 'test') 57 | end 58 | 59 | $package.serialize 'where_is_my_color.xlsx' 60 | -------------------------------------------------------------------------------- /examples/conditional_formatting/getting_barred.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | require 'axlsx' 5 | p = Axlsx::Package.new 6 | p.workbook do |wb| 7 | # define your regular styles 8 | styles = wb.styles 9 | title = styles.add_style :sz => 15, :b => true, :u => true 10 | default = styles.add_style :border => Axlsx::STYLE_THIN_BORDER 11 | header = styles.add_style :bg_color => '00', :fg_color => 'FF', :b => true 12 | money = styles.add_style :format_code => '#,###,##0', :border => Axlsx::STYLE_THIN_BORDER 13 | percent = styles.add_style :num_fmt => Axlsx::NUM_FMT_PERCENT, :border => Axlsx::STYLE_THIN_BORDER 14 | 15 | # define the style for conditional formatting - its the :dxf bit that counts! 16 | profitable = styles.add_style :fg_color => 'FF428751', :sz => 12, :type => :dxf, :b => true 17 | 18 | wb.add_worksheet(:name => 'Data Bar Conditional Formatting') do |ws| 19 | ws.add_row ['A$$le Q1 Revenue Historical Analysis (USD)'], :style => title 20 | ws.add_row 21 | ws.add_row ['Quarter', 'Profit', '% of Total'], :style => header 22 | ws.add_row ['Q1-2010', '15680000000', '=B4/SUM(B4:B7)'], :style => [default, money, percent] 23 | ws.add_row ['Q1-2011', '26740000000', '=B5/SUM(B4:B7)'], :style => [default, money, percent] 24 | ws.add_row ['Q1-2012', '46330000000', '=B6/SUM(B4:B7)'], :style => [default, money, percent] 25 | ws.add_row ['Q1-2013(est)', '72230000000', '=B7/SUM(B4:B7)'], :style => [default, money, percent] 26 | 27 | ws.merge_cells 'A1:C1' 28 | 29 | # Apply conditional formatting to range B4:B7 in the worksheet 30 | data_bar = Axlsx::DataBar.new 31 | ws.add_conditional_formatting 'B4:B7', { :type => :dataBar, 32 | :dxfId => profitable, 33 | :priority => 1, 34 | :data_bar => data_bar } 35 | end 36 | end 37 | p.serialize 'getting_barred.xlsx' 38 | -------------------------------------------------------------------------------- /examples/conditional_formatting/hitting_the_high_notes.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | require 'axlsx' 5 | p = Axlsx::Package.new 6 | p.workbook do |wb| 7 | # define your regular styles 8 | styles = wb.styles 9 | title = styles.add_style :sz => 15, :b => true, :u => true 10 | default = styles.add_style :border => Axlsx::STYLE_THIN_BORDER 11 | header = styles.add_style :bg_color => '00', :fg_color => 'FF', :b => true 12 | money = styles.add_style :format_code => '###,###,###,##0', :border => Axlsx::STYLE_THIN_BORDER 13 | percent = styles.add_style :num_fmt => Axlsx::NUM_FMT_PERCENT, :border => Axlsx::STYLE_THIN_BORDER 14 | 15 | # define the style for conditional formatting - its the :dxf bit that counts! 16 | profitable = styles.add_style :fg_color => 'FF428751', :sz => 12, :type => :dxf, :b => true 17 | 18 | wb.add_worksheet(:name => 'The High Notes') do |ws| 19 | ws.add_row ['A$$le Q1 Revenue Historical Analysis (USD)'], :style => title 20 | ws.add_row 21 | ws.add_row ['Quarter', 'Profit', '% of Total'], :style => header 22 | ws.add_row ['Q1-2010', '15680000000', '=B4/SUM(B4:B7)'], :style => [default, money, percent] 23 | ws.add_row ['Q1-2011', '26740000000', '=B5/SUM(B4:B7)'], :style => [default, money, percent] 24 | ws.add_row ['Q1-2012', '46330000000', '=B6/SUM(B4:B7)'], :style => [default, money, percent] 25 | ws.add_row ['Q1-2013(est)', '72230000000', '=B7/SUM(B4:B7)'], :style => [default, money, percent] 26 | 27 | ws.merge_cells 'A1:C1' 28 | 29 | # Apply conditional formatting to range B4:B7 in the worksheet 30 | ws.add_conditional_formatting 'B4:B7', { :type => :cellIs, 31 | :operator => :greaterThan, 32 | :formula => '27000000000', 33 | :dxfId => profitable, 34 | :priority => 1 } 35 | end 36 | end 37 | p.serialize 'the_high_notes.xlsx' 38 | -------------------------------------------------------------------------------- /examples/conditional_formatting/scaled_colors.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | require 'axlsx' 5 | p = Axlsx::Package.new 6 | p.workbook do |wb| 7 | # define your regular styles 8 | styles = wb.styles 9 | title = styles.add_style :sz => 15, :b => true, :u => true 10 | default = styles.add_style :border => Axlsx::STYLE_THIN_BORDER 11 | header = styles.add_style :bg_color => '00', :fg_color => 'FF', :b => true 12 | money = styles.add_style :format_code => '#,###,##0', :border => Axlsx::STYLE_THIN_BORDER 13 | percent = styles.add_style :num_fmt => Axlsx::NUM_FMT_PERCENT, :border => Axlsx::STYLE_THIN_BORDER 14 | 15 | # define the style for conditional formatting - its the :dxf bit that counts! 16 | profitable = styles.add_style :fg_color => 'FF428751', :sz => 12, :type => :dxf, :b => true 17 | 18 | wb.add_worksheet(:name => 'Scaled Colors') do |ws| 19 | ws.add_row ['A$$le Q1 Revenue Historical Analysis (USD)'], :style => title 20 | ws.add_row 21 | ws.add_row ['Quarter', 'Profit', '% of Total'], :style => header 22 | ws.add_row ['Q1-2010', '15680000000', '=B4/SUM(B4:B7)'], :style => [default, money, percent] 23 | ws.add_row ['Q1-2011', '26740000000', '=B5/SUM(B4:B7)'], :style => [default, money, percent] 24 | ws.add_row ['Q1-2012', '46330000000', '=B6/SUM(B4:B7)'], :style => [default, money, percent] 25 | ws.add_row ['Q1-2013(est)', '72230000000', '=B7/SUM(B4:B7)'], :style => [default, money, percent] 26 | 27 | ws.merge_cells 'A1:C1' 28 | 29 | # Apply conditional formatting to range B4:B7 in the worksheet 30 | color_scale = Axlsx::ColorScale.new 31 | ws.add_conditional_formatting 'B4:B7', { :type => :colorScale, 32 | :operator => :greaterThan, 33 | :formula => '27000000000', 34 | :dxfId => profitable, 35 | :priority => 1, 36 | :color_scale => color_scale } 37 | end 38 | end 39 | p.serialize 'scaled_colors.xlsx' 40 | -------------------------------------------------------------------------------- /examples/conditional_formatting/stop_and_go.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | require 'axlsx' 5 | p = Axlsx::Package.new 6 | p.workbook do |wb| 7 | # define your regular styles 8 | styles = wb.styles 9 | title = styles.add_style :sz => 15, :b => true, :u => true 10 | default = styles.add_style :border => Axlsx::STYLE_THIN_BORDER 11 | header = styles.add_style :bg_color => '00', :fg_color => 'FF', :b => true 12 | money = styles.add_style :format_code => '#,###,##0', :border => Axlsx::STYLE_THIN_BORDER 13 | percent = styles.add_style :num_fmt => Axlsx::NUM_FMT_PERCENT, :border => Axlsx::STYLE_THIN_BORDER 14 | 15 | # define the style for conditional formatting - its the :dxf bit that counts! 16 | profitable = styles.add_style :fg_color => 'FF428751', :sz => 12, :type => :dxf, :b => true 17 | 18 | wb.add_worksheet(:name => 'Downtown traffic') do |ws| 19 | ws.add_row ['A$$le Q1 Revenue Historical Analysis (USD)'], :style => title 20 | ws.add_row 21 | ws.add_row ['Quarter', 'Profit', '% of Total'], :style => header 22 | ws.add_row ['Q1-2010', '15680000000', '=B4/SUM(B4:B7)'], :style => [default, money, percent] 23 | ws.add_row ['Q1-2011', '26740000000', '=B5/SUM(B4:B7)'], :style => [default, money, percent] 24 | ws.add_row ['Q1-2012', '46330000000', '=B6/SUM(B4:B7)'], :style => [default, money, percent] 25 | ws.add_row ['Q1-2013(est)', '72230000000', '=B7/SUM(B4:B7)'], :style => [default, money, percent] 26 | 27 | ws.merge_cells 'A1:C1' 28 | 29 | # Apply conditional formatting to range B3:B7 in the worksheet 30 | icon_set = Axlsx::IconSet.new 31 | ws.add_conditional_formatting 'B3:B7', { :type => :iconSet, 32 | :dxfId => profitable, 33 | :priority => 1, 34 | :icon_set => icon_set } 35 | end 36 | end 37 | p.serialize 'stop_and_go.xlsx' 38 | -------------------------------------------------------------------------------- /examples/data_validation.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | require 'axlsx' 5 | 6 | p = Axlsx::Package.new 7 | p.workbook.add_worksheet do |ws| 8 | 9 | ws.add_row ["between", "lessThan", "bound list", "raw list"] 10 | 11 | 4.times do |i| 12 | ws.add_row [nil, nil, nil, nil, (i+1) * 2] 13 | end 14 | 15 | ws.add_data_validation("A2:A5", { 16 | :type => :whole, 17 | :operator => :between, 18 | :formula1 => '5', 19 | :formula2 => '10', 20 | :showErrorMessage => true, 21 | :errorTitle => 'Wrong input', 22 | :error => 'Only values between 5 and 10', 23 | :errorStyle => :information, 24 | :showInputMessage => true, 25 | :promptTitle => 'Be careful!', 26 | :prompt => %{We really want a value between 5 and 10, 27 | but it is OK if you want to break the rules. 28 | }}) 29 | 30 | ws.add_data_validation("B1:B5", { 31 | :type => :textLength, 32 | :operator => :lessThan, 33 | :formula1 => '10', 34 | :showErrorMessage => true, 35 | :errorTitle => 'Text is too long', 36 | :error => 'Max text length is 10 characters', 37 | :errorStyle => :stop, 38 | :showInputMessage => true, 39 | :promptTitle => 'Text length', 40 | :prompt => 'Max text length is 10 characters'}) 41 | 42 | ws.add_data_validation("C2:C5", { 43 | :type => :list, 44 | :formula1 => 'E2:E5', 45 | :showDropDown => false, 46 | :showErrorMessage => true, 47 | :errorTitle => '', 48 | :error => 'Only values from E2:E5', 49 | :errorStyle => :stop, 50 | :showInputMessage => true, 51 | :promptTitle => '', 52 | :prompt => 'Only values from E2:E5'}) 53 | 54 | ws.add_data_validation("D2:D5", { 55 | :type => :list, 56 | :formula1 => '"Red, Orange, NavyBlue"', 57 | :showDropDown => false, 58 | :showErrorMessage => true, 59 | :errorTitle => '', 60 | :error => 'Please use the dropdown selector to choose the value', 61 | :errorStyle => :stop, 62 | :showInputMessage => true, 63 | :prompt => '& Choose the value from the dropdown'}) 64 | 65 | end 66 | 67 | p.serialize 'data_validation.xlsx' 68 | -------------------------------------------------------------------------------- /examples/image1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randym/axlsx/8e7b4b3b7259103452c191f73ce0bf64f66033fe/examples/image1.gif -------------------------------------------------------------------------------- /examples/image1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randym/axlsx/8e7b4b3b7259103452c191f73ce0bf64f66033fe/examples/image1.jpeg -------------------------------------------------------------------------------- /examples/image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randym/axlsx/8e7b4b3b7259103452c191f73ce0bf64f66033fe/examples/image1.jpg -------------------------------------------------------------------------------- /examples/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randym/axlsx/8e7b4b3b7259103452c191f73ce0bf64f66033fe/examples/image1.png -------------------------------------------------------------------------------- /examples/image1_fake.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randym/axlsx/8e7b4b3b7259103452c191f73ce0bf64f66033fe/examples/image1_fake.jpg -------------------------------------------------------------------------------- /examples/ios_preview.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | 5 | #```ruby 6 | require 'axlsx' 7 | 8 | p = Axlsx::Package.new 9 | p.use_shared_strings = true 10 | s = p.workbook.add_worksheet(:name => "Formula test") 11 | s.add_row [1, 2, 3] 12 | s.add_row %w(a b c) 13 | s.add_row ["=SUM(A1:C1)"], :formula_values => [6] 14 | p.serialize "ios_preview.xlsx" 15 | -------------------------------------------------------------------------------- /examples/merge_cells.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | 5 | #```ruby 6 | require 'axlsx' 7 | package = Axlsx::Package.new 8 | package.workbook do |workbook| 9 | workbook.add_worksheet name: 'merged_cells' do |sheet| 10 | 4.times do 11 | sheet.add_row %w(a b c d e f g) 12 | end 13 | sheet.merge_cells "A1:A2" 14 | sheet.merge_cells "B1:B2" 15 | end 16 | end 17 | package.serialize 'merged_cells.xlsx' 18 | -------------------------------------------------------------------------------- /examples/no_grid_with_borders.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | 5 | #```ruby 6 | require 'axlsx' 7 | package = Axlsx::Package.new 8 | package.workbook do |workbook| 9 | workbook.styles do |s| 10 | gridstyle_border = s.add_style :border => { :style => :thin, :color =>"FFCDCDCD" } 11 | workbook.add_worksheet :name => "Custom Borders" do |sheet| 12 | sheet.sheet_view.show_grid_lines = false 13 | sheet.add_row ["with", "grid", "style"], :style => gridstyle_border 14 | sheet.add_row ["no", "border"] 15 | end 16 | end 17 | end 18 | package.serialize 'no_grid_with_borders.xlsx' 19 | -------------------------------------------------------------------------------- /examples/page_setup.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 2 | require 'axlsx' 3 | xls = Axlsx::Package.new 4 | wb = xls.workbook 5 | wb.add_worksheet do |ws| 6 | # Excel does not currently follow the specification and will ignore paper_width and paper_height so if you need 7 | # to for a paper size, be sure to set :paper_size 8 | ws.page_setup.set :paper_width => "210mm", :paper_size => 10, :paper_height => "297mm", :orientation => :landscape 9 | ws.add_row %w(AXLSX is cool) 10 | end 11 | xls.serialize "page_setup.xlsx" 12 | -------------------------------------------------------------------------------- /examples/pivot_table.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | 4 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 5 | require 'axlsx' 6 | 7 | p = Axlsx::Package.new 8 | wb = p.workbook 9 | 10 | # Create some data in a sheet 11 | def month 12 | %w(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec).sample 13 | end 14 | def year 15 | %w(2010 2011 2012).sample 16 | end 17 | def type 18 | %w(Meat Dairy Beverages Produce).sample 19 | end 20 | def sales 21 | rand(5000) 22 | end 23 | def region 24 | %w(East West North South).sample 25 | end 26 | 27 | wb.add_worksheet(:name => "Data Sheet") do |sheet| 28 | sheet.add_row ['Month', 'Year', 'Type', 'Sales', 'Region'] 29 | 30.times { sheet.add_row [month, year, type, sales, region] } 30 | sheet.add_pivot_table 'G4:L17', "A1:E31" do |pivot_table| 31 | pivot_table.rows = ['Month', 'Year'] 32 | pivot_table.columns = ['Type'] 33 | pivot_table.data = ['Sales'] 34 | pivot_table.pages = ['Region'] 35 | end 36 | end 37 | 38 | # Write the excel file 39 | p.serialize("pivot_table.xlsx") 40 | -------------------------------------------------------------------------------- /examples/pivot_test.rb: -------------------------------------------------------------------------------- 1 | class RandomReportGenerator 2 | def date 3 | Date.today.strftime("%m/%d/%Y") 4 | end 5 | def member_id 6 | @i ||= 0 7 | @i += 1 8 | end 9 | def name 10 | "John S." 11 | end 12 | def gender 13 | ["Male", "Female"].sample 14 | end 15 | def age 16 | rand(100) 17 | end 18 | def city 19 | ["New York", "Mountain View", "Newark", "Phoenix"].sample 20 | end 21 | def state 22 | ["NY", "CA", "NJ", "AZ"].sample 23 | end 24 | def parenting 25 | "Foo" 26 | end 27 | def student 28 | "Bar" 29 | end 30 | def income 31 | "Bar" 32 | end 33 | def education 34 | "Bar" 35 | end 36 | def answer 37 | ["Yes", "No", "Maybe", "I dont know"].sample 38 | end 39 | def run 40 | package = Axlsx::Package.new 41 | workbook = package.workbook 42 | 43 | workbook.add_worksheet(:name => "Data Sheet") do |sheet| 44 | sheet.add_row [ 45 | "Date", "Member ID", "Name", "Gender", "Age", "City", "State", 46 | "Parenting Status", "Student Status", "Income", "Education", "Answer" 47 | ] 48 | 30.times do 49 | sheet.add_row [date, member_id, name, gender, age, city, state, 50 | parenting, student, income, education, answer] 51 | end 52 | end 53 | 54 | workbook.add_worksheet(:name => "Summary") do |sheet| 55 | pivot_table = Axlsx::PivotTable.new 'A1:B15', "A1:L31", workbook.worksheets[0] 56 | pivot_table.rows = ['Answer'] 57 | pivot_table.data = [{:ref => "Member ID", :subtotal => "count"}] 58 | sheet.pivot_tables << pivot_table 59 | end 60 | 61 | package.serialize("pivot_table.xlsx") 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /examples/sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randym/axlsx/8e7b4b3b7259103452c191f73ce0bf64f66033fe/examples/sample.png -------------------------------------------------------------------------------- /examples/sheet_protection.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | require 'axlsx' 5 | 6 | p = Axlsx::Package.new 7 | p.workbook.add_worksheet(:name => 'Open Office') { |ws| ws.sheet_protection.password = 'fish' } 8 | p.serialize 'sheet_protection.xlsx' 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/split.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w -s 2 | # -*- coding: utf-8 -*- 3 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 4 | require 'axlsx' 5 | p = Axlsx::Package.new 6 | wb = p.workbook 7 | wb.add_worksheet name: 'pane' do |sheet| 8 | sheet.sheet_view.pane do |pane| 9 | pane.top_left_cell = "B2" 10 | pane.state = :frozen_split 11 | pane.y_split = 2 12 | pane.x_split = 1 13 | pane.active_pane = :bottom_right 14 | end 15 | end 16 | p.serialize 'pane.xlsx' 17 | -------------------------------------------------------------------------------- /examples/underline.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 2 | require 'axlsx' 3 | p = Axlsx::Package.new 4 | p.workbook do |wb| 5 | wb.styles do |s| 6 | no_underline = s.add_style :sz => 10, :b => true, :u => false, :alignment => { :horizontal=> :right } 7 | wb.add_worksheet(:name => 'wunderlinen') do |sheet| 8 | sheet.add_row %w{a b c really?}, :style => no_underline 9 | end 10 | end 11 | end 12 | p.serialize 'no_underline.xlsx' 13 | 14 | -------------------------------------------------------------------------------- /examples/wrap_text.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 2 | require 'axlsx' 3 | p = Axlsx::Package.new 4 | p.workbook do |wb| 5 | wb.styles do |s| 6 | wrap_text = s.add_style :fg_color=> "FFFFFF", 7 | :b => true, 8 | :bg_color => "004586", 9 | :sz => 12, 10 | :border => { :style => :thin, :color => "00" }, 11 | :alignment => { :horizontal => :center, 12 | :vertical => :center , 13 | :wrap_text => true} 14 | wb.add_worksheet(:name => 'wrap text') do |sheet| 15 | sheet.add_row ['Torp, White and Cronin'], :style => wrap_text 16 | # Forcing the column to be a bit narrow so we can see if the text wrap. 17 | sheet.column_info.first.width = 5 18 | end 19 | end 20 | end 21 | p.serialize 'wrap_text.xlsx' 22 | -------------------------------------------------------------------------------- /lib/axlsx/content_type/abstract_content_type.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # This class extracts the common parts from Default and Override 4 | class AbstractContentType 5 | 6 | include Axlsx::OptionsParser 7 | 8 | # Initializes an abstract content type 9 | # @see Default, Override 10 | def initialize(options={}) 11 | parse_options options 12 | end 13 | 14 | # The type of content. 15 | # @return [String] 16 | attr_reader :content_type 17 | alias :ContentType :content_type 18 | 19 | # The content type. 20 | # @see Axlsx#validate_content_type 21 | def content_type=(v) Axlsx::validate_content_type v; @content_type = v end 22 | alias :ContentType= :content_type= 23 | 24 | # Serialize the contenty type to xml 25 | def to_xml_string(node_name = '', str = '') 26 | str << "<#{node_name} " 27 | str << instance_values.map { |key, value| Axlsx::camel(key) << '="' << value.to_s << '"' }.join(' ') 28 | str << '/>' 29 | end 30 | 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/axlsx/content_type/content_type.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | require 'axlsx/content_type/abstract_content_type.rb' 4 | require 'axlsx/content_type/default.rb' 5 | require 'axlsx/content_type/override.rb' 6 | 7 | # ContentTypes used in the package. This is automatically managed by the package package. 8 | class ContentType < SimpleTypedList 9 | 10 | def initialize 11 | super [Override, Default] 12 | end 13 | 14 | # Serializes the object 15 | # @param [String] str 16 | # @return [String] 17 | def to_xml_string(str = '') 18 | str << '' 19 | str << ('') 20 | each { |type| type.to_xml_string(str) } 21 | str << '' 22 | end 23 | 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /lib/axlsx/content_type/default.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | 4 | # An default content part. These parts are automatically created by for you based on the content of your package. 5 | class Default < AbstractContentType 6 | 7 | # The serialization node name for this class 8 | NODE_NAME = 'Default' 9 | 10 | # The extension of the content type. 11 | # @return [String] 12 | attr_reader :extension 13 | alias :Extension :extension 14 | 15 | # Sets the file extension for this content type. 16 | def extension=(v) Axlsx::validate_string v; @extension = v end 17 | alias :Extension= :extension= 18 | 19 | # Serializes this object to xml 20 | def to_xml_string(str ='') 21 | super(NODE_NAME, str) 22 | end 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /lib/axlsx/content_type/override.rb: -------------------------------------------------------------------------------- 1 | 2 | # encoding: UTF-8 3 | module Axlsx 4 | 5 | # An override content part. These parts are automatically created by for you based on the content of your package. 6 | class Override < AbstractContentType 7 | 8 | # Serialization node name for this object 9 | NODE_NAME = 'Override' 10 | 11 | # The name and location of the part. 12 | # @return [String] 13 | attr_reader :part_name 14 | alias :PartName :part_name 15 | 16 | # The name and location of the part. 17 | def part_name=(v) Axlsx::validate_string v; @part_name = v end 18 | alias :PartName= :part_name= 19 | 20 | # Serializes this object to xml 21 | def to_xml_string(str = '') 22 | super(NODE_NAME, str) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/axlsx/doc_props/core.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | 4 | # The core object for the package. 5 | # @note Packages manage their own core object. 6 | # @see Package#core 7 | class Core 8 | 9 | # Creates a new Core object. 10 | # @option options [String] creator 11 | # @option options [Time] created 12 | def initialize(options={}) 13 | @creator = options[:creator] || 'axlsx' 14 | @created = options[:created] 15 | end 16 | 17 | # The author of the document. By default this is 'axlsx' 18 | # @return [String] 19 | attr_accessor :creator 20 | 21 | # Creation time of the document. If nil, the current time will be used. 22 | attr_accessor :created 23 | 24 | # serializes the core.xml document 25 | # @return [String] 26 | def to_xml_string(str = '') 27 | str << '' 28 | str << ('') 31 | str << ('' << self.creator << '') 32 | str << ('' << (created || Time.now).strftime('%Y-%m-%dT%H:%M:%S') << 'Z') 33 | str << '0' 34 | str << '' 35 | end 36 | 37 | end 38 | 39 | end 40 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/ax_data_source.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # An axis data source that can contain referenced or literal strings or numbers 4 | # @note only string data types are supported - mainly because we have not implemented a chart type that requires a numerical axis value 5 | class AxDataSource < NumDataSource 6 | 7 | # creates a new NumDataSource object 8 | # @option options [Array] data An array of Cells or Numeric objects 9 | # @option options [Symbol] tag_name see tag_name 10 | def initialize(options={}) 11 | @tag_name = :cat 12 | @data_type = StrData 13 | @ref_tag_name = :strRef 14 | super(options) 15 | end 16 | 17 | # allowed element tag names for serialization 18 | # @return [Array] 19 | def self.allowed_tag_names 20 | [:xVal, :cat] 21 | end 22 | 23 | end 24 | 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/axes.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # The Axes class creates and manages axis information and 4 | # serialization for charts. 5 | class Axes 6 | 7 | # @param [Hash] options options used to generate axis each key 8 | # should be an axis name like :val_axis and its value should be the 9 | # class of the axis type to construct. The :cat_axis, if there is one, 10 | # must come first (we assume a Ruby 1.9+ Hash or an OrderedHash). 11 | def initialize(options={}) 12 | raise(ArgumentError, "CatAxis must come first") if options.keys.include?(:cat_axis) && options.keys.first != :cat_axis 13 | options.each do |name, axis_class| 14 | add_axis(name, axis_class) 15 | end 16 | end 17 | 18 | # [] provides assiciative access to a specic axis store in an axes 19 | # instance. 20 | # @return [Axis] 21 | def [](name) 22 | axes.assoc(name)[1] 23 | end 24 | 25 | # Serializes the object 26 | # @param [String] str 27 | # @param [Hash] options 28 | # @option options ids 29 | # If the ids option is specified only the axis identifier is 30 | # serialized. Otherwise, each axis is serialized in full. 31 | def to_xml_string(str = '', options = {}) 32 | if options[:ids] 33 | # CatAxis must come first in the XML (for Microsoft Excel at least) 34 | sorted = axes.sort_by { |name, axis| axis.kind_of?(CatAxis) ? 0 : 1 } 35 | sorted.each { |axis| str << ('') } 36 | else 37 | axes.each { |axis| axis[1].to_xml_string(str) } 38 | end 39 | end 40 | 41 | # Adds an axis to the collection 42 | # @param [Symbol] name The name of the axis 43 | # @param [Axis] axis_class The axis class to generate 44 | def add_axis(name, axis_class) 45 | axis = axis_class.new 46 | set_cross_axis(axis) 47 | axes << [name, axis] 48 | end 49 | 50 | private 51 | 52 | def axes 53 | @axes ||= [] 54 | end 55 | 56 | def set_cross_axis(axis) 57 | axes.first[1].cross_axis = axis if axes.size == 1 58 | axis.cross_axis = axes.first[1] unless axes.empty? 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/bubble_chart.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | 4 | # The BubbleChart allows you to insert a bubble chart into your worksheet 5 | # @see Worksheet#add_chart 6 | # @see Chart#add_series 7 | # @see README for an example 8 | class BubbleChart < Chart 9 | 10 | include Axlsx::OptionsParser 11 | 12 | # the x value axis 13 | # @return [ValAxis] 14 | def x_val_axis 15 | axes[:x_val_axis] 16 | end 17 | alias :xValAxis :x_val_axis 18 | 19 | # the y value axis 20 | # @return [ValAxis] 21 | def y_val_axis 22 | axes[:y_val_axis] 23 | end 24 | alias :yValAxis :y_val_axis 25 | 26 | # Creates a new bubble chart 27 | def initialize(frame, options={}) 28 | @vary_colors = 0 29 | 30 | super(frame, options) 31 | @series_type = BubbleSeries 32 | @d_lbls = nil 33 | parse_options options 34 | end 35 | 36 | # Serializes the object 37 | # @param [String] str 38 | # @return [String] 39 | def to_xml_string(str = '') 40 | super(str) do 41 | str << '' 42 | str << ('') 43 | @series.each { |ser| ser.to_xml_string(str) } 44 | d_lbls.to_xml_string(str) if @d_lbls 45 | axes.to_xml_string(str, :ids => true) 46 | str << '' 47 | axes.to_xml_string(str) 48 | end 49 | str 50 | end 51 | 52 | # The axes for the bubble chart. BubbleChart has an x_val_axis and 53 | # a y_val_axis 54 | # @return [Axes] 55 | def axes 56 | @axes ||= Axes.new(:x_val_axis => ValAxis, :y_val_axis => ValAxis) 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/graphic_frame.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # A graphic frame defines a container for a chart object 4 | # @note The recommended way to manage charts is Worksheet#add_chart 5 | # @see Worksheet#add_chart 6 | class GraphicFrame 7 | 8 | # A reference to the chart object associated with this frame 9 | # @return [Chart] 10 | attr_reader :chart 11 | 12 | # A anchor that holds this frame 13 | # @return [TwoCellAnchor] 14 | attr_reader :anchor 15 | 16 | # Creates a new GraphicFrame object 17 | # @param [TwoCellAnchor] anchor 18 | # @param [Class] chart_type 19 | def initialize(anchor, chart_type, options) 20 | DataTypeValidator.validate "Drawing.chart_type", Chart, chart_type 21 | @anchor = anchor 22 | @chart = chart_type.new(self, options) 23 | end 24 | 25 | # The relationship id for this graphic frame. 26 | # @return [String] 27 | def rId 28 | @anchor.drawing.relationships.for(chart).Id 29 | end 30 | 31 | # Serializes the object 32 | # @param [String] str 33 | # @return [String] 34 | def to_xml_string(str = '') 35 | # macro attribute should be optional! 36 | str << '' 37 | str << '' 38 | str << ('') 39 | str << '' 40 | str << '' 41 | str << '' 42 | str << '' 43 | str << '' 44 | str << '' 45 | str << '' 46 | str << ('') 47 | str << ('') 48 | str << '' 49 | str << '' 50 | str << '' 51 | end 52 | 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/num_data.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | module Axlsx 3 | 4 | #This class specifies data for a particular data point. It is used for both numCache and numLit object 5 | class NumData 6 | 7 | include Axlsx::OptionsParser 8 | 9 | # creates a new NumVal object 10 | # @option options [String] formatCode 11 | # @option options [Array] :data 12 | # @see StrData 13 | def initialize(options={}) 14 | @format_code = "General" 15 | @pt = SimpleTypedList.new NumVal 16 | parse_options options 17 | end 18 | 19 | # A string representing the format code to apply. For more information see see the SpreadsheetML numFmt element's (§18.8.30) formatCode attribute. 20 | # @return [String] 21 | attr_reader :format_code 22 | 23 | # Creates the val objects for this data set. I am not overly confident this is going to play nicely with time and data types. 24 | # @param [Array] values An array of cells or values. 25 | def data=(values=[]) 26 | @tag_name = values.first.is_a?(Cell) ? :numCache : :numLit 27 | values.each do |value| 28 | value = value.is_formula? ? 0 : value.value if value.is_a?(Cell) 29 | @pt << NumVal.new(:v => value) 30 | end 31 | end 32 | 33 | # @see format_code 34 | def format_code=(v='General') 35 | Axlsx::validate_string(v) 36 | @format_code = v 37 | end 38 | 39 | # serialize the object 40 | def to_xml_string(str = "") 41 | str << ('') 42 | str << ('' << format_code.to_s << '') 43 | str << ('') 44 | @pt.each_with_index do |num_val, index| 45 | num_val.to_xml_string index, str 46 | end 47 | str << ('') 48 | end 49 | 50 | end 51 | 52 | end 53 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/num_data_source.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A numeric data source for use by charts. 4 | class NumDataSource 5 | 6 | include Axlsx::OptionsParser 7 | 8 | # creates a new NumDataSource object 9 | # @option options [Array] data An array of Cells or Numeric objects 10 | # @option options [Symbol] tag_name see tag_name 11 | def initialize(options={}) 12 | # override these three in child classes 13 | @data_type ||= NumData 14 | @tag_name ||= :val 15 | @ref_tag_name ||= :numRef 16 | 17 | @f = nil 18 | @data = @data_type.new(options) 19 | if options[:data] && options[:data].first.is_a?(Cell) 20 | @f = Axlsx::cell_range(options[:data]) 21 | end 22 | parse_options options 23 | end 24 | 25 | 26 | # The tag name to use when serializing this data source. 27 | # Only items defined in allowed_tag_names are allowed 28 | # @return [Symbol] 29 | attr_reader :tag_name 30 | 31 | attr_reader :data 32 | 33 | # allowed element tag names 34 | # @return [Array] 35 | def self.allowed_tag_names 36 | [:yVal, :val, :bubbleSize] 37 | end 38 | 39 | # sets the tag name for this data source 40 | # @param [Symbol] v One of the allowed_tag_names 41 | def tag_name=(v) 42 | Axlsx::RestrictionValidator.validate "#{self.class.name}.tag_name", self.class.allowed_tag_names, v 43 | @tag_name = v 44 | end 45 | 46 | # serialize the object 47 | # @param [String] str 48 | def to_xml_string(str="") 49 | str << ('') 50 | if @f 51 | str << ('') 52 | str << ('' << @f.to_s << '') 53 | end 54 | @data.to_xml_string str 55 | if @f 56 | str << ('') 57 | end 58 | str << ('') 59 | end 60 | end 61 | end 62 | 63 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/num_val.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | module Axlsx 3 | 4 | #This class specifies data for a particular data point. 5 | class NumVal < StrVal 6 | 7 | # A string representing the format code to apply. 8 | # For more information see see the SpreadsheetML numFmt element's (§18.8.30) formatCode attribute. 9 | # @return [String] 10 | attr_reader :format_code 11 | 12 | # creates a new NumVal object 13 | # @option options [String] formatCode 14 | # @option options [Integer] v 15 | def initialize(options={}) 16 | @format_code = "General" 17 | super(options) 18 | end 19 | 20 | # @see format_code 21 | def format_code=(v) 22 | Axlsx::validate_string(v) 23 | @format_code = v 24 | end 25 | 26 | # serialize the object 27 | def to_xml_string(idx, str = "") 28 | Axlsx::validate_unsigned_int(idx) 29 | if !v.to_s.empty? 30 | str << ('' << v.to_s << '') 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/picture_locking.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # The picture locking class defines the locking properties for pictures in your workbook. 4 | class PictureLocking 5 | 6 | include Axlsx::OptionsParser 7 | include Axlsx::SerializedAttributes 8 | include Axlsx::Accessors 9 | 10 | boolean_attr_accessor :noGrp, :noSelect, :noRot, :noChangeAspect, 11 | :noMove, :noResize, :noEditPoints, :noAdjustHandles, 12 | :noChangeArrowheads, :noChangeShapeType 13 | 14 | serializable_attributes :noGrp, :noSelect, :noRot, :noChangeAspect, 15 | :noMove, :noResize, :noEditPoints, :noAdjustHandles, 16 | :noChangeArrowheads, :noChangeShapeType 17 | 18 | # Creates a new PictureLocking object 19 | # @option options [Boolean] noGrp 20 | # @option options [Boolean] noSelect 21 | # @option options [Boolean] noRot 22 | # @option options [Boolean] noChangeAspect 23 | # @option options [Boolean] noMove 24 | # @option options [Boolean] noResize 25 | # @option options [Boolean] noEditPoints 26 | # @option options [Boolean] noAdjustHandles 27 | # @option options [Boolean] noChangeArrowheads 28 | # @option options [Boolean] noChangeShapeType 29 | def initialize(options={}) 30 | @noChangeAspect = true 31 | parse_options options 32 | end 33 | 34 | # Serializes the object 35 | # @param [String] str 36 | # @return [String] 37 | def to_xml_string(str = '') 38 | serialized_tag('a:picLocks', str) 39 | end 40 | 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/pie_3D_chart.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | 4 | 5 | # The Pie3DChart is a three dimentional piechart (who would have guessed?) that you can add to your worksheet. 6 | # @see Worksheet#add_chart 7 | # @see Chart#add_series 8 | # @see README for an example 9 | class Pie3DChart < Chart 10 | 11 | # Creates a new pie chart object 12 | # @param [GraphicFrame] frame The workbook that owns this chart. 13 | # @option options [Cell, String] title 14 | # @option options [Boolean] show_legend 15 | # @option options [Symbol] grouping 16 | # @option options [String] gap_depth 17 | # @option options [Integer] rot_x 18 | # @option options [String] h_percent 19 | # @option options [Integer] rot_y 20 | # @option options [String] depth_percent 21 | # @option options [Boolean] r_ang_ax 22 | # @option options [Integer] perspective 23 | # @see Chart 24 | # @see View3D 25 | def initialize(frame, options={}) 26 | @vary_colors = true 27 | super(frame, options) 28 | @series_type = PieSeries 29 | @view_3D = View3D.new({:rot_x =>30, :perspective=>30}.merge(options)) 30 | @d_lbls = nil 31 | end 32 | 33 | # Serializes the object 34 | # @param [String] str 35 | # @return [String] 36 | def to_xml_string(str = '') 37 | super(str) do 38 | str << '' 39 | str << ('') 40 | @series.each { |ser| ser.to_xml_string(str) } 41 | d_lbls.to_xml_string(str) if @d_lbls 42 | str << '' 43 | end 44 | end 45 | 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/scaling.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # The Scaling class defines axis scaling 4 | class Scaling 5 | 6 | include Axlsx::OptionsParser 7 | 8 | # creates a new Scaling object 9 | # @option options [Integer] logBase 10 | # @option options [Symbol] orientation 11 | # @option options [Float] max 12 | # @option options [Float] min 13 | def initialize(options={}) 14 | @orientation = :minMax 15 | @logBase, @min, @max = nil, nil, nil 16 | parse_options options 17 | end 18 | 19 | # logarithmic base for a logarithmic axis. 20 | # must be between 2 and 1000 21 | # @return [Integer] 22 | attr_reader :logBase 23 | 24 | # the orientation of the axis 25 | # must be one of [:minMax, :maxMin] 26 | # @return [Symbol] 27 | attr_reader :orientation 28 | 29 | # the maximum scaling 30 | # @return [Float] 31 | attr_reader :max 32 | 33 | # the minimu scaling 34 | # @return [Float] 35 | attr_reader :min 36 | 37 | # @see logBase 38 | def logBase=(v) DataTypeValidator.validate "Scaling.logBase", [Integer], v, lambda { |arg| arg >= 2 && arg <= 1000}; @logBase = v; end 39 | # @see orientation 40 | def orientation=(v) RestrictionValidator.validate "Scaling.orientation", [:minMax, :maxMin], v; @orientation = v; end 41 | # @see max 42 | def max=(v) DataTypeValidator.validate "Scaling.max", Float, v; @max = v; end 43 | 44 | # @see min 45 | def min=(v) DataTypeValidator.validate "Scaling.min", Float, v; @min = v; end 46 | 47 | # Serializes the object 48 | # @param [String] str 49 | # @return [String] 50 | def to_xml_string(str = '') 51 | str << '' 52 | str << ('') unless @logBase.nil? 53 | str << ('') unless @orientation.nil? 54 | str << ('') unless @min.nil? 55 | str << ('') unless @max.nil? 56 | str << '' 57 | end 58 | 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/ser_axis.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | #A SerAxis object defines a series axis 4 | class SerAxis < Axis 5 | 6 | # The number of tick lables to skip between labels 7 | # @return [Integer] 8 | attr_reader :tick_lbl_skip 9 | alias :tickLblSkip :tick_lbl_skip 10 | 11 | # The number of tickmarks to be skipped before the next one is rendered. 12 | # @return [Boolean] 13 | attr_reader :tick_mark_skip 14 | alias :tickMarkSkip :tick_mark_skip 15 | 16 | # Creates a new SerAxis object 17 | # @option options [Integer] tick_lbl_skip 18 | # @option options [Integer] tick_mark_skip 19 | def initialize(options={}) 20 | @tick_lbl_skip, @tick_mark_skip = 1, 1 21 | super(options) 22 | end 23 | 24 | # @see tickLblSkip 25 | def tick_lbl_skip=(v) Axlsx::validate_unsigned_int(v); @tick_lbl_skip = v; end 26 | alias :tickLblSkip= :tick_lbl_skip= 27 | 28 | # @see tickMarkSkip 29 | def tick_mark_skip=(v) Axlsx::validate_unsigned_int(v); @tick_mark_skip = v; end 30 | alias :tickMarkSkip= :tick_mark_skip= 31 | 32 | # Serializes the object 33 | # @param [String] str 34 | # @return [String] 35 | def to_xml_string(str = '') 36 | str << '' 37 | super(str) 38 | str << ('') unless @tick_lbl_skip.nil? 39 | str << ('') unless @tick_mark_skip.nil? 40 | str << '' 41 | end 42 | end 43 | 44 | 45 | end 46 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/series.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # A Series defines the common series attributes and is the super class for all concrete series types. 4 | # @note The recommended way to manage series is to use Chart#add_series 5 | # @see Worksheet#add_chart 6 | # @see Chart#add_series 7 | class Series 8 | 9 | include Axlsx::OptionsParser 10 | 11 | # The chart that owns this series 12 | # @return [Chart] 13 | attr_reader :chart 14 | 15 | # The title of the series 16 | # @return [SeriesTitle] 17 | attr_reader :title 18 | 19 | # Creates a new series 20 | # @param [Chart] chart 21 | # @option options [Integer] order 22 | # @option options [String] title 23 | def initialize(chart, options={}) 24 | @order = nil 25 | self.chart = chart 26 | @chart.series << self 27 | parse_options options 28 | end 29 | 30 | # The index of this series in the chart's series. 31 | # @return [Integer] 32 | def index 33 | @chart.series.index(self) 34 | end 35 | 36 | # The order of this series in the chart's series. By default the order is the index of the series. 37 | # @return [Integer] 38 | def order 39 | @order || index 40 | end 41 | 42 | # @see order 43 | def order=(v) Axlsx::validate_unsigned_int(v); @order = v; end 44 | 45 | # @see title 46 | def title=(v) 47 | v = SeriesTitle.new(v) if v.is_a?(String) || v.is_a?(Cell) 48 | DataTypeValidator.validate "#{self.class}.title", SeriesTitle, v 49 | @title = v 50 | end 51 | 52 | private 53 | 54 | # assigns the chart for this series 55 | def chart=(v) DataTypeValidator.validate "Series.chart", Chart, v; @chart = v; end 56 | 57 | # Serializes the object 58 | # @param [String] str 59 | # @return [String] 60 | def to_xml_string(str = '') 61 | str << '' 62 | str << ('') 63 | str << ('') 64 | title.to_xml_string(str) unless title.nil? 65 | yield if block_given? 66 | str << '' 67 | end 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/series_title.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # A series title is a Title with a slightly different serialization than chart titles. 4 | class SeriesTitle < Title 5 | 6 | # Serializes the object 7 | # @param [String] str 8 | # @return [String] 9 | def to_xml_string(str = '') 10 | str << '' 11 | str << '' 12 | str << ('' << Axlsx::cell_range([@cell]) << '') 13 | str << '' 14 | str << '' 15 | str << '' 16 | str << ('' << @text << '') 17 | str << '' 18 | str << '' 19 | str << '' 20 | str << '' 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/str_data.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | module Axlsx 3 | 4 | #This specifies the last string data used for a chart. (e.g. strLit and strCache) 5 | # This class is extended for NumData to include the formatCode attribute required for numLit and numCache 6 | class StrData 7 | 8 | include Axlsx::OptionsParser 9 | 10 | # creates a new StrVal object 11 | # @option options [Array] :data 12 | # @option options [String] :tag_name 13 | def initialize(options={}) 14 | @tag_prefix = :str 15 | @type = StrVal 16 | @pt = SimpleTypedList.new(@type) 17 | parse_options options 18 | end 19 | 20 | # Creates the val objects for this data set. I am not overly confident this is going to play nicely with time and data types. 21 | # @param [Array] values An array of cells or values. 22 | def data=(values=[]) 23 | @tag_name = values.first.is_a?(Cell) ? :strCache : :strLit 24 | values.each do |value| 25 | v = value.is_a?(Cell) ? value.value : value 26 | @pt << @type.new(:v => v) 27 | end 28 | end 29 | 30 | # serialize the object 31 | def to_xml_string(str = "") 32 | str << ('') 33 | str << ('') 34 | @pt.each_with_index do |value, index| 35 | value.to_xml_string index, str 36 | end 37 | str << ('') 38 | end 39 | 40 | end 41 | 42 | end 43 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/str_val.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | module Axlsx 3 | 4 | #This class specifies data for a particular data point. 5 | class StrVal 6 | 7 | include Axlsx::OptionsParser 8 | 9 | # creates a new StrVal object 10 | # @option options [String] v 11 | def initialize(options={}) 12 | @v = "" 13 | @idx = 0 14 | parse_options options 15 | end 16 | 17 | # a string value. 18 | # @return [String] 19 | attr_reader :v 20 | 21 | # @see v 22 | def v=(v) 23 | @v = v.to_s 24 | end 25 | 26 | # serialize the object 27 | def to_xml_string(idx, str = "") 28 | Axlsx::validate_unsigned_int(idx) 29 | if !v.to_s.empty? 30 | str << ('' << ::CGI.escapeHTML(v.to_s) << '') 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/val_axis.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # the ValAxis class defines a chart value axis. 4 | class ValAxis < Axis 5 | 6 | # This element specifies how the value axis crosses the category axis. 7 | # must be one of [:between, :midCat] 8 | # @return [Symbol] 9 | attr_reader :cross_between 10 | alias :crossBetween :cross_between 11 | 12 | # Creates a new ValAxis object 13 | # @option options [Symbol] crosses_between 14 | def initialize(options={}) 15 | self.cross_between = :between 16 | super(options) 17 | end 18 | 19 | # @see cross_between 20 | def cross_between=(v) 21 | RestrictionValidator.validate "ValAxis.cross_between", [:between, :midCat], v 22 | @cross_between = v 23 | end 24 | alias :crossBetween= :cross_between= 25 | 26 | # Serializes the object 27 | # @param [String] str 28 | # @return [String] 29 | def to_xml_string(str = '') 30 | str << '' 31 | super(str) 32 | str << ('') 33 | str << '' 34 | end 35 | 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/axlsx/drawing/vml_drawing.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # a vml drawing used for comments in excel. 4 | class VmlDrawing 5 | 6 | # creates a new Vml Drawing object. 7 | # @param [Comments] comments the comments object this drawing is associated with 8 | def initialize(comments) 9 | raise ArgumentError, "you must provide a comments object" unless comments.is_a?(Comments) 10 | @comments = comments 11 | end 12 | 13 | # The part name for this vml drawing 14 | # @return [String] 15 | def pn 16 | "#{VML_DRAWING_PN}" % (@comments.worksheet.index + 1) 17 | end 18 | 19 | # serialize the vml_drawing to xml. 20 | # @param [String] str 21 | # @return [String] 22 | def to_xml_string(str = '') 23 | str << < 27 | 28 | 29 | 30 | 32 | 33 | 34 | 35 | BAD_PROGRAMMER 36 | @comments.each { |comment| comment.vml_shape.to_xml_string str } 37 | str << "" 38 | 39 | end 40 | 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/axlsx/rels/relationships.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | require 'axlsx/rels/relationship.rb' 4 | 5 | # Relationships are a collection of Relations that define how package parts are related. 6 | # @note The package automatically manages releationships. 7 | class Relationships < SimpleTypedList 8 | 9 | # Creates a new Relationships collection based on SimpleTypedList 10 | def initialize 11 | super Relationship 12 | end 13 | 14 | # The relationship instance for the given source object, or nil if none exists. 15 | # @see Relationship#source_obj 16 | # @return [Relationship] 17 | def for(source_obj) 18 | find{ |rel| rel.source_obj == source_obj } 19 | end 20 | 21 | # serialize relationships 22 | # @param [String] str 23 | # @return [String] 24 | def to_xml_string(str = '') 25 | str << '' 26 | str << ('') 27 | each{ |rel| rel.to_xml_string(str) } 28 | str << '' 29 | end 30 | 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/axlsx/stylesheet/cell_protection.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # CellProtection stores information about locking or hiding cells in spreadsheet. 4 | # @note Using Styles#add_style is the recommended way to manage cell protection. 5 | # @see Styles#add_style 6 | class CellProtection 7 | 8 | include Axlsx::OptionsParser 9 | include Axlsx::SerializedAttributes 10 | 11 | serializable_attributes :hidden, :locked 12 | 13 | # specifies locking for cells that have the style containing this protection 14 | # @return [Boolean] 15 | attr_reader :hidden 16 | 17 | # specifies if the cells that have the style containing this protection 18 | # @return [Boolean] 19 | attr_reader :locked 20 | 21 | # Creates a new CellProtection 22 | # @option options [Boolean] hidden value for hidden protection 23 | # @option options [Boolean] locked value for locked protection 24 | def initialize(options={}) 25 | parse_options options 26 | end 27 | 28 | # @see hidden 29 | def hidden=(v) Axlsx::validate_boolean v; @hidden = v end 30 | # @see locked 31 | def locked=(v) Axlsx::validate_boolean v; @locked = v end 32 | 33 | # Serializes the object 34 | # @param [String] str 35 | # @return [String] 36 | def to_xml_string(str = '') 37 | serialized_tag('protection', str) 38 | end 39 | 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/axlsx/stylesheet/fill.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # The Fill is a formatting object that manages the background color, and pattern for cells. 4 | # @note The recommended way to manage styles in your workbook is to use Styles#add_style. 5 | # @see Styles#add_style 6 | # @see PatternFill 7 | # @see GradientFill 8 | class Fill 9 | 10 | # The type of fill 11 | # @return [PatternFill, GradientFill] 12 | attr_reader :fill_type 13 | 14 | # Creates a new Fill object 15 | # @param [PatternFill, GradientFill] fill_type 16 | # @raise [ArgumentError] if the fill_type parameter is not a PatternFill or a GradientFill instance 17 | def initialize(fill_type) 18 | self.fill_type = fill_type 19 | end 20 | 21 | # Serializes the object 22 | # @param [String] str 23 | # @return [String] 24 | def to_xml_string(str = '') 25 | str << '' 26 | @fill_type.to_xml_string(str) 27 | str << '' 28 | end 29 | 30 | # @see fill_type 31 | def fill_type=(v) DataTypeValidator.validate "Fill.fill_type", [PatternFill, GradientFill], v; @fill_type = v; end 32 | 33 | 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/axlsx/stylesheet/gradient_stop.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # The GradientStop object represents a color point in a gradient. 4 | # @see Open Office XML Part 1 §18.8.24 5 | class GradientStop 6 | # The color for this gradient stop 7 | # @return [Color] 8 | # @see Color 9 | attr_reader :color 10 | 11 | # The position of the color 12 | # @return [Float] 13 | attr_reader :position 14 | 15 | # Creates a new GradientStop object 16 | # @param [Color] color 17 | # @param [Float] position 18 | def initialize(color, position) 19 | self.color = color 20 | self.position = position 21 | end 22 | 23 | # @see color 24 | def color=(v) DataTypeValidator.validate "GradientStop.color", Color, v; @color=v end 25 | # @see position 26 | def position=(v) DataTypeValidator.validate "GradientStop.position", Float, v, lambda { |arg| arg >= 0 && arg <= 1}; @position = v end 27 | 28 | # Serializes the object 29 | # @param [String] str 30 | # @return [String] 31 | def to_xml_string(str = '') 32 | str << ('') 33 | self.color.to_xml_string(str) 34 | str << '' 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/axlsx/stylesheet/table_style.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # A single table style definition and is a collection for tableStyleElements 4 | # @note Table are not supported in this version and only the defaults required for a valid workbook are created. 5 | class TableStyle < SimpleTypedList 6 | 7 | include Axlsx::OptionsParser 8 | include Axlsx::SerializedAttributes 9 | 10 | # creates a new TableStyle object 11 | # @raise [ArgumentError] if name option is not provided. 12 | # @param [String] name 13 | # @option options [Boolean] pivot 14 | # @option options [Boolean] table 15 | def initialize(name, options={}) 16 | self.name = name 17 | parse_options options 18 | super TableStyleElement 19 | end 20 | 21 | serializable_attributes :name, :pivot, :table 22 | 23 | # The name of this table style 24 | # @return [string] 25 | attr_reader :name 26 | 27 | # indicates if this style should be applied to pivot tables 28 | # @return [Boolean] 29 | attr_reader :pivot 30 | 31 | # indicates if this style should be applied to tables 32 | # @return [Boolean] 33 | attr_reader :table 34 | 35 | # @see name 36 | def name=(v) Axlsx::validate_string v; @name=v end 37 | # @see pivot 38 | def pivot=(v) Axlsx::validate_boolean v; @pivot=v end 39 | # @see table 40 | def table=(v) Axlsx::validate_boolean v; @table=v end 41 | 42 | # Serializes the object 43 | # @param [String] str 44 | # @return [String] 45 | def to_xml_string(str = '') 46 | str << ' self.size} 48 | str << '>' 49 | each { |table_style_el| table_style_el.to_xml_string(str) } 50 | str << '' 51 | end 52 | 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/axlsx/stylesheet/table_styles.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # TableStyles represents a collection of style definitions for table styles and pivot table styles. 4 | # @note Support for custom table styles does not exist in this version. Many of the classes required are defined in preparation for future release. Please do not attempt to add custom table styles. 5 | class TableStyles < SimpleTypedList 6 | 7 | include Axlsx::SerializedAttributes 8 | 9 | # Creates a new TableStyles object that is a container for TableStyle objects 10 | # @option options [String] defaultTableStyle 11 | # @option options [String] defaultPivotStyle 12 | def initialize(options={}) 13 | @defaultTableStyle = options[:defaultTableStyle] || "TableStyleMedium9" 14 | @defaultPivotStyle = options[:defaultPivotStyle] || "PivotStyleLight16" 15 | super TableStyle 16 | end 17 | 18 | serializable_attributes :defaultTableStyle, :defaultPivotStyle 19 | 20 | # The default table style. The default value is 'TableStyleMedium9' 21 | # @return [String] 22 | attr_reader :defaultTableStyle 23 | 24 | # The default pivot table style. The default value is 'PivotStyleLight6' 25 | # @return [String] 26 | attr_reader :defaultPivotStyle 27 | 28 | # @see defaultTableStyle 29 | def defaultTableStyle=(v) Axlsx::validate_string(v); @defaultTableStyle = v; end 30 | # @see defaultPivotStyle 31 | def defaultPivotStyle=(v) Axlsx::validate_string(v); @defaultPivotStyle = v; end 32 | 33 | # Serializes the object 34 | # @param [String] str 35 | # @return [String] 36 | def to_xml_string(str = '') 37 | str << ' self.size } 39 | str << '>' 40 | each { |table_style| table_style.to_xml_string(str) } 41 | str << '' 42 | end 43 | 44 | end 45 | 46 | end 47 | -------------------------------------------------------------------------------- /lib/axlsx/util/mime_type_utils.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | # This module defines some utils related with mime type detection 3 | module MimeTypeUtils 4 | # Detect a file mime type 5 | # @param [String] v File path 6 | # @return [String] File mime type 7 | def self.get_mime_type(v) 8 | MimeMagic.by_magic(File.open(v)).to_s 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/axlsx/util/options_parser.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | # This module defines a single method for parsing options in class 3 | # initializers. 4 | module OptionsParser 5 | 6 | # Parses an options hash by calling any defined method by the same 7 | # name of the key postfixed with an '=' 8 | # @param [Hash] options Options to parse. 9 | def parse_options(options={}) 10 | options.each do |key, value| 11 | key = :"#{key}=" 12 | self.send(key, value) if !value.nil? && self.respond_to?(key) 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/axlsx/util/parser.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | module Axlsx 3 | # The Parser module mixes in a number of methods to help in generating a model from xml 4 | # This module is not included in the axlsx library at this time. It is for future development only, 5 | module Parser 6 | 7 | # The xml to be parsed 8 | attr_accessor :parser_xml 9 | 10 | # parse and assign string attribute 11 | def parse_string attr_name, xpath 12 | send("#{attr_name}=", parse_value(xpath)) 13 | end 14 | 15 | # parse convert and assign node text to symbol 16 | def parse_symbol attr_name, xpath 17 | v = parse_value xpath 18 | v = v.to_sym unless v.nil? 19 | send("#{attr_name}=", v) 20 | end 21 | 22 | # parse, convert and assign note text to integer 23 | def parse_integer attr_name, xpath 24 | v = parse_value xpath 25 | v = v.to_i if v.respond_to?(:to_i) 26 | send("#{attr_name}=", v) 27 | end 28 | 29 | # parse, convert and assign node text to float 30 | def parse_float attr_name, xpath 31 | v = parse_value xpath 32 | v = v.to_f if v.respond_to?(:to_f) 33 | send("#{attr_name}=", v) 34 | end 35 | 36 | # return node text based on xpath 37 | def parse_value xpath 38 | node = parser_xml.xpath(xpath) 39 | return nil if node.empty? 40 | node.text.strip 41 | end 42 | 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/axlsx/version.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # The current version 4 | VERSION = "3.0.0.pre" 5 | end 6 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/defined_names.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | # a simple types list of DefinedName objects 3 | class DefinedNames < SimpleTypedList 4 | 5 | # creates the DefinedNames object 6 | def initialize 7 | super DefinedName 8 | end 9 | 10 | # Serialize to xml 11 | # @param [String] str 12 | # @return [String] 13 | def to_xml_string(str = '') 14 | return if empty? 15 | str << '' 16 | each { |defined_name| defined_name.to_xml_string(str) } 17 | str << '' 18 | end 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/workbook_views.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | # a simple types list of BookView objects 3 | class WorkbookViews < SimpleTypedList 4 | 5 | # creates the book views object 6 | def initialize 7 | super WorkbookView 8 | end 9 | 10 | # Serialize to xml 11 | # @param [String] str 12 | # @return [String] 13 | def to_xml_string(str = '') 14 | return if empty? 15 | str << "" 16 | each { |view| view.to_xml_string(str) } 17 | str << '' 18 | end 19 | end 20 | end 21 | 22 | 23 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/break.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # The Break class stores the details for row and column page breaks. 4 | # @see RowBreaks, ColBreaks 5 | class Break 6 | 7 | include Axlsx::OptionsParser 8 | include Axlsx::Accessors 9 | include Axlsx::SerializedAttributes 10 | 11 | # Creates a new Break object 12 | # @param options A hash of attribute options for this break. 13 | # @option options [Integer] id Zero-based row or column Id of the page break. Breaks occur above the specified row and left of the specified column. 14 | # @option options [Integer] min Zero-based index of start row or column of the break. For row breaks, specifies column index; for column breaks, specifies row index. 15 | # @option options [Integer] max Zero-based index of end row or column of the break. For row breaks, specifies column index; for column breaks, specifies row index. 16 | # @option options [Boolean] man Manual Break flag. 1 means the break is a manually inserted break. 17 | # @option option [Boolean] pt Flag indicating that a PivotTable created this break. 18 | def initialize(options={}) 19 | parse_options options 20 | yield self if block_given? 21 | end 22 | 23 | unsigned_int_attr_accessor :id, :min, :max 24 | 25 | boolean_attr_accessor :man, :pt 26 | 27 | serializable_attributes :id, :min, :max, :man, :pt 28 | 29 | # serializes the break to xml 30 | def to_xml_string(str='') 31 | serialized_tag('brk', str) 32 | end 33 | end 34 | end 35 | 36 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/cfvos.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | #A collection of Cfvo objects that initializes with the required 4 | #first two items 5 | class Cfvos < SimpleTypedList 6 | 7 | def initialize 8 | super(Cfvo) 9 | end 10 | 11 | # Serialize the Cfvo object 12 | # @param [String] str 13 | # @return [String] 14 | def to_xml_string(str='') 15 | each { |cfvo| cfvo.to_xml_string(str) } 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/col_breaks.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A collection of Brake objects. 4 | # Please do not use this class directly. Instead use 5 | # Worksheet#add_break 6 | class ColBreaks < SimpleTypedList 7 | 8 | # Instantiates a new list restricted to Break types 9 | def initialize 10 | super Break 11 | end 12 | 13 | # A column break specific helper for adding a break. 14 | # @param [Hash] options A list of options to pass into the Break object 15 | # The max and man options are fixed, however any other valid option for 16 | # Break will be passed to the created break object. 17 | # @see Break 18 | def add_break(options) 19 | self << Break.new(options.merge(:max => 1048575, :man => true)) 20 | last 21 | end 22 | 23 | # Serialize the collection to xml 24 | # @param [String] str The string to append this lists xml to. 25 | # 26 | # 27 | # 28 | def to_xml_string(str='') 29 | return if empty? 30 | str << ('') 31 | each { |brk| brk.to_xml_string(str) } 32 | str << '' 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/cols.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # The cols class manages the col object used to manage column widths. 4 | # This is where the magic happens with autowidth 5 | class Cols < SimpleTypedList 6 | 7 | def initialize(worksheet) 8 | raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) 9 | super Col 10 | @worksheet = worksheet 11 | end 12 | 13 | # Serialize the Cols object 14 | # @param [String] str 15 | # @return [String] 16 | def to_xml_string(str = '') 17 | return if empty? 18 | str << '' 19 | each { |item| item.to_xml_string(str) } 20 | str << '' 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/conditional_formattings.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A simple, self serializing class for storing conditional formattings 4 | class ConditionalFormattings < SimpleTypedList 5 | 6 | # creates a new Tables object 7 | def initialize(worksheet) 8 | raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) 9 | super ConditionalFormatting 10 | @worksheet = worksheet 11 | end 12 | 13 | # The worksheet that owns this collection of tables 14 | # @return [Worksheet] 15 | attr_reader :worksheet 16 | 17 | # serialize the conditional formattings 18 | def to_xml_string(str = "") 19 | return if empty? 20 | each { |item| item.to_xml_string(str) } 21 | end 22 | end 23 | 24 | end 25 | 26 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/data_validations.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A simple, self serializing class for storing conditional formattings 4 | class DataValidations < SimpleTypedList 5 | 6 | # creates a new Tables object 7 | def initialize(worksheet) 8 | raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) 9 | super DataValidation 10 | @worksheet = worksheet 11 | end 12 | 13 | # The worksheet that owns this collection of tables 14 | # @return [Worksheet] 15 | attr_reader :worksheet 16 | 17 | # serialize the conditional formattings 18 | def to_xml_string(str = "") 19 | return if empty? 20 | str << "" 21 | each { |item| item.to_xml_string(str) } 22 | str << '' 23 | end 24 | end 25 | 26 | end 27 | 28 | 29 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/date_time_converter.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | require "date" 3 | 4 | module Axlsx 5 | # The DateTimeConverter class converts both data and time types to their apprpriate excel serializations 6 | class DateTimeConverter 7 | 8 | # The date_to_serial method converts Date objects to the equivelant excel serialized forms 9 | # @param [Date] date the date to be serialized 10 | # @return [Numeric] 11 | def self.date_to_serial(date) 12 | epoch = Axlsx::Workbook::date1904 ? Date.new(1904) : Date.new(1899, 12, 30) 13 | offset_date = date.respond_to?(:utc_offset) ? date + date.utc_offset.seconds : date 14 | (offset_date - epoch).to_f 15 | end 16 | 17 | # The time_to_serial methond converts a Time object its excel serialized form. 18 | # @param [Time] time the time to be serialized 19 | # @return [Numeric] 20 | def self.time_to_serial(time) 21 | # Using hardcoded offsets here as some operating systems will not except 22 | # a 'negative' offset from the ruby epoch. 23 | epoch1900 = -2209161600.0 # Time.utc(1899, 12, 30).to_i 24 | epoch1904 = -2082844800.0 # Time.utc(1904, 1, 1).to_i 25 | seconds_per_day = 86400.0 # 60*60*24 26 | epoch = Axlsx::Workbook::date1904 ? epoch1904 : epoch1900 27 | (time.utc_offset + time.to_f - epoch)/seconds_per_day 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/dimension.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # This class manages the dimensions for a worksheet. 4 | # While this node is optional in the specification some readers like 5 | # LibraOffice require this node to render the sheet 6 | class Dimension 7 | 8 | # the default value for the first cell in the dimension 9 | # @return [String] 10 | def self.default_first 11 | @@default_first ||= 'A1' 12 | end 13 | 14 | # the default value for the last cell in the dimension 15 | # @return [String] 16 | def self.default_last 17 | @@default_last ||= 'AA200' 18 | end 19 | 20 | # Creates a new dimension object 21 | # @param[Worksheet] worksheet - the worksheet this dimension applies 22 | # to. 23 | def initialize(worksheet) 24 | raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) 25 | @worksheet = worksheet 26 | end 27 | 28 | attr_reader :worksheet 29 | 30 | # the full refernece for this dimension 31 | # @return [String] 32 | def sqref 33 | "#{first_cell_reference}:#{last_cell_reference}" 34 | end 35 | 36 | # serialize the object 37 | # @return [String] 38 | def to_xml_string(str = '') 39 | return if worksheet.rows.empty? 40 | str << "" % sqref 41 | end 42 | 43 | # The first cell in the dimension 44 | # @return [String] 45 | def first_cell_reference 46 | dimension_reference(worksheet.rows.first.first, Dimension.default_first) 47 | end 48 | 49 | # the last cell in the dimension 50 | # @return [String] 51 | def last_cell_reference 52 | dimension_reference(worksheet.rows.last.last, Dimension.default_last) 53 | end 54 | 55 | private 56 | 57 | # Returns the reference of a cell or the default specified 58 | # @return [String] 59 | def dimension_reference(cell, default) 60 | return default unless cell.respond_to?(:r) 61 | cell.r 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/merged_cells.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A simple list of merged cells 4 | class MergedCells < SimpleTypedList 5 | 6 | # creates a new MergedCells object 7 | # @param [Worksheet] worksheet 8 | def initialize(worksheet) 9 | raise ArgumentError, 'you must provide a worksheet' unless worksheet.is_a?(Worksheet) 10 | super String 11 | end 12 | 13 | # adds cells to the merged cells collection 14 | # @param [Array||String] cells The cells to add to the merged cells 15 | # collection. This can be an array of actual cells or a string style 16 | # range like 'A1:C1' 17 | def add(cells) 18 | self << if cells.is_a?(String) 19 | cells 20 | elsif cells.is_a?(Array) 21 | Axlsx::cell_range(cells, false) 22 | elsif cells.is_a?(Row) 23 | Axlsx::cell_range(cells, false) 24 | end 25 | end 26 | 27 | # serialize the object 28 | # @param [String] str 29 | # @return [String] 30 | def to_xml_string(str = '') 31 | return if empty? 32 | str << "" 33 | each { |merged_cell| str << "" } 34 | str << '' 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/outline_pr.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # The OutlinePr class manages serialization of a worksheet's outlinePr element, which provides various 4 | # options to control outlining. 5 | class OutlinePr 6 | include Axlsx::OptionsParser 7 | include Axlsx::Accessors 8 | include Axlsx::SerializedAttributes 9 | 10 | serializable_attributes :summary_below, 11 | :summary_right, 12 | :apply_styles 13 | 14 | # These attributes are all boolean so I'm doing a bit of a hand 15 | # waving magic show to set up the attriubte accessors 16 | boolean_attr_accessor :summary_below, 17 | :summary_right, 18 | :apply_styles 19 | 20 | # Creates a new OutlinePr object 21 | # @param [Hash] options used to create the outline_pr 22 | def initialize(options = {}) 23 | parse_options options 24 | end 25 | 26 | # Serialize the object 27 | # @param [String] str serialized output will be appended to this object if provided. 28 | # @return [String] 29 | def to_xml_string(str = '') 30 | str << "" 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/page_set_up_pr.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # Page setup properties of the worksheet 4 | # This class name is not a typo, its spec. 5 | class PageSetUpPr 6 | 7 | include Axlsx::OptionsParser 8 | include Axlsx::SerializedAttributes 9 | 10 | # creates a new page setup properties object 11 | # @param [Hash] options 12 | # @option [Boolean] auto_page_breaks Flag indicating whether the sheet displays Automatic Page Breaks. 13 | # @option [Boolean] fit_to_page Flag indicating whether the Fit to Page print option is enabled. 14 | def initialize(options = {}) 15 | parse_options options 16 | end 17 | 18 | serializable_attributes :auto_page_breaks, :fit_to_page 19 | 20 | attr_reader :auto_page_breaks 21 | attr_reader :fit_to_page 22 | 23 | # Flag indicating whether the Fit to Page print option is enabled. 24 | # @param [Boolean] value 25 | # @return [Boolean] 26 | def fit_to_page=(value) 27 | Axlsx.validate_boolean value 28 | @fit_to_page = value 29 | end 30 | 31 | # Flag indicating whether the sheet displays Automatic Page Breaks. 32 | # @param [Boolean] value 33 | # @return [Boolean] 34 | def auto_page_breaks=(value) 35 | Axlsx.validate_boolean value 36 | @auto_page_breaks = value 37 | end 38 | 39 | # serialize to xml 40 | def to_xml_string(str='') 41 | str << ('') 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/pivot_tables.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A simple, self serializing class for storing pivot tables 4 | class PivotTables < SimpleTypedList 5 | 6 | # creates a new Tables object 7 | def initialize(worksheet) 8 | raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) 9 | super PivotTable 10 | @worksheet = worksheet 11 | end 12 | 13 | # The worksheet that owns this collection of pivot tables 14 | # @return [Worksheet] 15 | attr_reader :worksheet 16 | 17 | # returns the relationships required by this collection 18 | def relationships 19 | return [] if empty? 20 | map{ |pivot_table| Relationship.new(pivot_table, PIVOT_TABLE_R, "../#{pivot_table.pn}") } 21 | end 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/print_options.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | # Options for printing a worksheet. All options are boolean and false by default. 3 | # 4 | # @note The recommended way to manage print options is via Worksheet#print_options 5 | # @see Worksheet#print_options 6 | # @see Worksheet#initialize 7 | class PrintOptions 8 | 9 | include Axlsx::OptionsParser 10 | include Axlsx::SerializedAttributes 11 | include Axlsx::Accessors 12 | # Creates a new PrintOptions object 13 | # @option options [Boolean] grid_lines Whether grid lines should be printed 14 | # @option options [Boolean] headings Whether row and column headings should be printed 15 | # @option options [Boolean] horizontal_centered Whether the content should be centered horizontally 16 | # @option options [Boolean] vertical_centered Whether the content should be centered vertically 17 | def initialize(options = {}) 18 | @grid_lines = @headings = @horizontal_centered = @vertical_centered = false 19 | set(options) 20 | end 21 | 22 | serializable_attributes :grid_lines, :headings, :horizontal_centered, :vertical_centered 23 | boolean_attr_accessor :grid_lines, :headings, :horizontal_centered, :vertical_centered 24 | 25 | # Set some or all options at once. 26 | # @param [Hash] options The options to set (possible keys are :grid_lines, :headings, :horizontal_centered, and :vertical_centered). 27 | def set(options) 28 | parse_options options 29 | end 30 | 31 | # Serializes the page options element. 32 | # @note As all attributes default to "false" according to the xml schema definition, the generated xml includes only those attributes that are set to true. 33 | # @param [String] str 34 | # @return [String] 35 | def to_xml_string(str = '') 36 | serialized_tag 'printOptions', str 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/protected_range.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | # The Protected Range class represents a set of cells in the worksheet 3 | # @note the recommended way to manage protected ranges with via Worksheet#protect_range 4 | # @see Worksheet#protect_range 5 | class ProtectedRange 6 | 7 | include Axlsx::OptionsParser 8 | include Axlsx::SerializedAttributes 9 | 10 | # Initializes a new protected range object 11 | # @option [String] sqref The cell range reference to protect. This can be an absolute or a relateve range however, it only applies to the current sheet. 12 | # @option [String] name An optional name for the protected name. 13 | def initialize(options={}) 14 | parse_options options 15 | yield self if block_given? 16 | end 17 | 18 | serializable_attributes :sqref, :name 19 | # The reference for the protected range 20 | # @return [String] 21 | attr_reader :sqref 22 | 23 | # The name of the protected range 24 | # @return [String] 25 | attr_reader :name 26 | 27 | # @see sqref 28 | def sqref=(v) 29 | Axlsx.validate_string(v) 30 | @sqref = v 31 | end 32 | 33 | # @see name 34 | def name=(v) 35 | Axlsx.validate_string(v) 36 | @name = v 37 | end 38 | 39 | # serializes the proteted range 40 | # @param [String] str if this string object is provided we append 41 | # our output to that object. Use this - it helps limit the number of 42 | # objects created during serialization 43 | def to_xml_string(str="") 44 | serialized_tag 'protectedRange', str 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/protected_ranges.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A self serializing collection of ranges that should be protected in 4 | # the worksheet 5 | class ProtectedRanges < SimpleTypedList 6 | 7 | attr_reader :worksheet 8 | 9 | def initialize(worksheet) 10 | raise ArgumentError, 'You must provide a worksheet' unless worksheet.is_a?(Worksheet) 11 | super ProtectedRange 12 | @worksheet = worksheet 13 | end 14 | 15 | # Adds a protected range 16 | # @param [Array|String] cells A string range reference or array of cells that will be protected 17 | def add_range(cells) 18 | sqref = if cells.is_a?(String) 19 | cells 20 | elsif cells.is_a?(SimpleTypedList) || cells.is_a?(Array) 21 | Axlsx::cell_range(cells, false) 22 | end 23 | self << ProtectedRange.new(:sqref => sqref, :name => "Range#{size}") 24 | last 25 | end 26 | 27 | # Serializes the protected ranges 28 | # @param [String] str 29 | # @return [String] 30 | def to_xml_string(str = '') 31 | return if empty? 32 | str << '' 33 | each { |range| range.to_xml_string(str) } 34 | str << '' 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/rich_text.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A simple, self serializing class for storing TextRuns 4 | class RichText < SimpleTypedList 5 | 6 | # creates a new RichText collection 7 | # @param [String] text -optional The text to use in creating the first RichTextRun 8 | # @param [Object] options -optional The options to use in creating the first RichTextRun 9 | # @yield [RichText] self 10 | def initialize(text = nil, options={}) 11 | super(RichTextRun) 12 | add_run(text, options) unless text.nil? 13 | yield self if block_given? 14 | end 15 | 16 | # The cell that owns this RichText collection 17 | attr_reader :cell 18 | 19 | # Assign the cell for this RichText collection 20 | # @param [Cell] cell The cell which all RichTextRuns in the collection will belong to 21 | def cell=(cell) 22 | @cell = cell 23 | each { |run| run.cell = cell } 24 | end 25 | 26 | # Calculates the longest autowidth of the RichTextRuns in this collection 27 | # @return [Number] 28 | def autowidth 29 | widtharray = [0] # Are arrays the best way of solving this problem? 30 | each { |run| run.autowidth(widtharray) } 31 | widtharray.max 32 | end 33 | 34 | # Creates and adds a RichTextRun to this collectino 35 | # @param [String] text The text to use in creating a new RichTextRun 36 | # @param [Object] options The options to use in creating the new RichTextRun 37 | def add_run(text, options={}) 38 | self << RichTextRun.new(text, options) 39 | end 40 | 41 | # The RichTextRuns we own 42 | # @return [RichText] 43 | def runs 44 | self 45 | end 46 | 47 | # renders the RichTextRuns in this collection 48 | # @param [String] str 49 | # @return [String] 50 | def to_xml_string(str='') 51 | each{ |run| run.to_xml_string(str) } 52 | str 53 | end 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/row_breaks.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A collection of break objects that define row breaks (page breaks) for printing and preview 4 | 5 | class RowBreaks < SimpleTypedList 6 | 7 | def initialize 8 | super Break 9 | end 10 | 11 | # Adds a row break 12 | # @param [Hash] options The options for the break to be created. 13 | # max and man values are fixed. 14 | # @see Break 15 | def add_break(options) 16 | # force feed the excel default 17 | self << Break.new(options.merge(:max => 16383, :man => true)) 18 | last 19 | end 20 | 21 | # 22 | # 23 | # 24 | # 25 | # 26 | def to_xml_string(str='') 27 | return if empty? 28 | str << ('') 29 | each { |brk| brk.to_xml_string(str) } 30 | str << '' 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/sheet_calc_pr.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # the SheetCalcPr object for the worksheet 4 | # This object contains calculation properties for the worksheet. 5 | class SheetCalcPr 6 | include Axlsx::OptionsParser 7 | include Axlsx::SerializedAttributes 8 | include Axlsx::Accessors 9 | # creates a new SheetCalcPr 10 | # @param [Hash] options Options for this object 11 | # @option [Boolean] full_calc_on_load @see full_calc_on_load 12 | def initialize(options={}) 13 | @full_calc_on_load = true 14 | parse_options options 15 | end 16 | 17 | boolean_attr_accessor :full_calc_on_load 18 | 19 | serializable_attributes :full_calc_on_load 20 | 21 | # Serialize the object 22 | # @param [String] str the string to append this objects serialized 23 | # content to. 24 | # @return [String] 25 | def to_xml_string(str='') 26 | str << "" 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/sheet_data.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # This class manages the serialization of rows for worksheets 4 | class SheetData 5 | 6 | # Creates a new SheetData object 7 | # @param [Worksheet] worksheet The worksheet that owns this sheet data. 8 | def initialize(worksheet) 9 | raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) 10 | @worksheet = worksheet 11 | end 12 | 13 | attr_reader :worksheet 14 | 15 | # Serialize the sheet data 16 | # @param [String] str the string this objects serializaton will be concacted to. 17 | # @return [String] 18 | def to_xml_string(str = '') 19 | str << '' 20 | worksheet.rows.each_with_index do |row, index| 21 | row.to_xml_string(index, str) 22 | end 23 | str << '' 24 | end 25 | 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/table_style_info.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # The table style info class manages style attributes for defined tables in 4 | # a worksheet 5 | class TableStyleInfo 6 | include Axlsx::OptionsParser 7 | include Axlsx::SerializedAttributes 8 | include Axlsx::Accessors 9 | # creates a new TableStyleInfo instance 10 | # @param [Hash] options 11 | # @option [Boolean] show_first_column indicates if the first column should 12 | # be shown 13 | # @option [Boolean] show_last_column indicates if the last column should 14 | # be shown 15 | # @option [Boolean] show_column_stripes indicates if column stripes should 16 | # be shown 17 | # @option [Boolean] show_row_stripes indicates if row stripes should be shown 18 | # @option [String] name The name of the style to apply to your table. 19 | # Only predefined styles are currently supported. 20 | # @see Annex G. (normative) Predefined SpreadsheetML Style Definitions in part 1 of the specification. 21 | def initialize(options = {}) 22 | initialize_defaults 23 | @name = 'TableStyleMedium9' 24 | parse_options options 25 | end 26 | 27 | # boolean attributes for this object 28 | boolean_attr_accessor :show_first_column, :show_last_column, :show_row_stripes, :show_column_stripes 29 | serializable_attributes :show_first_column, :show_last_column, :show_row_stripes, :show_column_stripes, 30 | :name 31 | 32 | # Initialize all the values to false as Excel requires them to 33 | # explicitly be disabled or all will show. 34 | def initialize_defaults 35 | %w(show_first_column show_last_column show_row_stripes show_column_stripes).each do |attr| 36 | self.send("#{attr}=", 0) 37 | end 38 | end 39 | 40 | # The name of the table style. 41 | attr_accessor :name 42 | 43 | # seralizes this object to an xml string 44 | # @param [String] str the string to contact this objects serialization to. 45 | def to_xml_string(str = '') 46 | serialized_tag('tableStyleInfo', str) 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/tables.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A simple, self serializing class for storing tables 4 | class Tables < SimpleTypedList 5 | 6 | # creates a new Tables object 7 | def initialize(worksheet) 8 | raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) 9 | super Table 10 | @worksheet = worksheet 11 | end 12 | 13 | # The worksheet that owns this collection of tables 14 | # @return [Worksheet] 15 | attr_reader :worksheet 16 | 17 | # returns the relationships required by this collection 18 | def relationships 19 | return [] if empty? 20 | map{ |table| Relationship.new(table, TABLE_R, "../#{table.pn}") } 21 | end 22 | 23 | # renders the tables xml 24 | # @param [String] str 25 | # @return [String] 26 | def to_xml_string(str = "") 27 | return if empty? 28 | str << "" 29 | each { |table| str << "" } 30 | str << '' 31 | end 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/worksheet_comments.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # A wraper class for comments that defines its on worksheet 4 | # serailization 5 | class WorksheetComments 6 | 7 | # Creates a new WorksheetComments object 8 | # param [Worksheet] worksheet The worksheet comments in thes object belong to 9 | def initialize(worksheet) 10 | raise ArugumentError, 'You must provide a worksheet' unless worksheet.is_a?(Worksheet) 11 | @worksheet = worksheet 12 | end 13 | 14 | attr_reader :worksheet 15 | 16 | # The comments for this worksheet. 17 | # @return [Comments] 18 | def comments 19 | @comments ||= Comments.new(worksheet) 20 | end 21 | 22 | # Adds a comment 23 | # @param [Hash] options 24 | # @see Comments#add_comment 25 | def add_comment(options={}) 26 | comments.add_comment(options) 27 | end 28 | 29 | # The relationships defined by this objects comments collection 30 | # @return [Relationships] 31 | def relationships 32 | return [] unless has_comments? 33 | comments.relationships 34 | end 35 | 36 | 37 | # Helper method to tell us if there are comments in the comments collection 38 | # @return [Boolean] 39 | def has_comments? 40 | !comments.empty? 41 | end 42 | 43 | # The relationship id of the VML drawing that will render the comments. 44 | # @see Relationship#Id 45 | # @return [String] 46 | def drawing_rId 47 | comments.relationships.find{ |r| r.Type == VML_DRAWING_R }.Id 48 | end 49 | 50 | # Seraalize the object 51 | # @param [String] str 52 | # @return [String] 53 | def to_xml_string(str = '') 54 | return unless has_comments? 55 | str << "" 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/worksheet_drawing.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | # This is a utility class for serialing the drawing node in a 4 | # worksheet. Drawing objects have their own serialization that exports 5 | # a drawing document. This is only for the single node in the 6 | # worksheet 7 | class WorksheetDrawing 8 | 9 | # Creates a new WorksheetDrawing 10 | # @param [Worksheet] worksheet 11 | def initialize(worksheet) 12 | raise ArgumentError, 'you must provide a worksheet' unless worksheet.is_a?(Worksheet) 13 | @worksheet = worksheet 14 | @drawing = nil 15 | end 16 | 17 | attr_reader :worksheet 18 | 19 | attr_reader :drawing 20 | 21 | # adds a chart to the drawing object 22 | # @param [Class] chart_type The type of chart to add 23 | # @param [Hash] options Options to pass on to the drawing and chart 24 | # @see Worksheet#add_chart 25 | def add_chart(chart_type, options) 26 | @drawing ||= Drawing.new worksheet 27 | drawing.add_chart(chart_type, options) 28 | end 29 | 30 | # adds an image to the drawing object 31 | # @param [Hash] options Options to pass on to the drawing and image 32 | # @see Worksheet#add_image 33 | def add_image(options) 34 | @drawing ||= Drawing.new(worksheet) 35 | drawing.add_image(options) 36 | end 37 | 38 | # helper method to tell us if the drawing has something in it or not 39 | # @return [Boolean] 40 | def has_drawing? 41 | @drawing.is_a? Drawing 42 | end 43 | 44 | # The relationship instance for this drawing. 45 | # @return [Relationship] 46 | def relationship 47 | return unless has_drawing? 48 | Relationship.new(self, DRAWING_R, "../#{drawing.pn}") 49 | end 50 | 51 | # Serialize the drawing for the worksheet 52 | # @param [String] str 53 | def to_xml_string(str = '') 54 | return unless has_drawing? 55 | str << "" 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb: -------------------------------------------------------------------------------- 1 | module Axlsx 2 | 3 | #A collection of hyperlink objects for a worksheet 4 | class WorksheetHyperlinks < SimpleTypedList 5 | 6 | # Creates a new Hyperlinks collection 7 | # @param [Worksheet] worksheet the worksheet that owns these hyperlinks 8 | def initialize(worksheet) 9 | DataTypeValidator.validate "Hyperlinks.worksheet", [Worksheet], worksheet 10 | @worksheet = worksheet 11 | super WorksheetHyperlink 12 | end 13 | 14 | # Creates and adds a new hyperlink based on the options provided 15 | # @see WorksheetHyperlink#initialize 16 | # @return [WorksheetHyperlink] 17 | def add(options) 18 | self << WorksheetHyperlink.new(@worksheet, options) 19 | last 20 | end 21 | 22 | # The relationships required by this collection's hyperlinks 23 | # @return Array 24 | def relationships 25 | return [] if empty? 26 | map { |hyperlink| hyperlink.relationship } 27 | end 28 | 29 | # seralize the collection of hyperlinks 30 | # @return [String] 31 | def to_xml_string(str='') 32 | return if empty? 33 | str << '' 34 | each { |hyperlink| hyperlink.to_xml_string(str) } 35 | str << '' 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/schema/dcmitype.xsd: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | DCMI Type Vocabulary XML Schema 13 | XML Schema for http://purl.org/dc/dcmitype/ namespace 14 | 15 | Created 2003-04-02 16 | 17 | Created by 18 | 19 | Tim Cole (t-cole3@uiuc.edu) 20 | Tom Habing (thabing@uiuc.edu) 21 | Jane Hunter (jane@dstc.edu.au) 22 | Pete Johnston (p.johnston@ukoln.ac.uk), 23 | Carl Lagoze (lagoze@cs.cornell.edu) 24 | 25 | This schema defines a simpleType which enumerates 26 | the allowable values for the DCMI Type Vocabulary. 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /lib/schema/dml-compatibility.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /lib/schema/dml-lockedCanvas.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /lib/schema/dml-picture.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /lib/schema/opc-contentTypes.xsd: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /lib/schema/opc-relationships.xsd: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /lib/schema/shared-additionalCharacteristics.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /lib/schema/shared-customXmlDataProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /lib/schema/shared-customXmlSchemaProperties.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /lib/schema/shared-relationshipReference.xsd: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /lib/schema/vml-presentationDrawing.xsd: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /test/benchmark.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -s 2 | $:.unshift "#{File.dirname(__FILE__)}/../lib" 3 | require 'axlsx' 4 | require 'csv' 5 | require 'benchmark' 6 | Axlsx::trust_input = true 7 | row = [] 8 | input = (32..126).to_a.pack('U*').chars.to_a 9 | 20.times { row << input.shuffle.join} 10 | times = 3000 11 | Benchmark.bmbm(30) do |x| 12 | 13 | x.report('axlsx_noautowidth') { 14 | p = Axlsx::Package.new 15 | p.workbook do |wb| 16 | wb.add_worksheet do |sheet| 17 | times.times do 18 | sheet << row 19 | end 20 | end 21 | end 22 | p.use_autowidth = false 23 | p.serialize("example_noautowidth.xlsx") 24 | } 25 | 26 | x.report('axlsx') { 27 | p = Axlsx::Package.new 28 | p.workbook do |wb| 29 | wb.add_worksheet do |sheet| 30 | times.times do 31 | sheet << row 32 | end 33 | end 34 | end 35 | p.serialize("example_autowidth.xlsx") 36 | } 37 | 38 | x.report('axlsx_shared') { 39 | p = Axlsx::Package.new 40 | p.workbook do |wb| 41 | wb.add_worksheet do |sheet| 42 | times.times do 43 | sheet << row 44 | end 45 | end 46 | end 47 | p.use_shared_strings = true 48 | p.serialize("example_shared.xlsx") 49 | } 50 | 51 | x.report('axlsx_stream') { 52 | p = Axlsx::Package.new 53 | p.workbook do |wb| 54 | wb.add_worksheet do |sheet| 55 | times.times do 56 | sheet << row 57 | end 58 | end 59 | end 60 | s = p.to_stream() 61 | File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) } 62 | } 63 | 64 | x.report('csv') { 65 | CSV.open("example.csv", "wb") do |csv| 66 | times.times do 67 | csv << row 68 | end 69 | end 70 | } 71 | end 72 | File.delete("example.csv", "example_streamed.xlsx", "example_shared.xlsx", "example_autowidth.xlsx", "example_noautowidth.xlsx") 73 | -------------------------------------------------------------------------------- /test/content_type/tc_default.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | require 'tc_helper.rb' 3 | 4 | class TestDefault < Test::Unit::TestCase 5 | 6 | def test_content_type_restriction 7 | assert_raise(ArgumentError, "raises argument error if invlalid ContentType is") { Axlsx::Default.new :ContentType=>"asdf" } 8 | end 9 | 10 | def test_to_xml_string 11 | type = Axlsx::Default.new :Extension=>"xml", :ContentType=>Axlsx::XML_CT 12 | doc = Nokogiri::XML(type.to_xml_string) 13 | assert_equal(doc.xpath("Default[@ContentType='#{Axlsx::XML_CT}']").size, 1) 14 | assert_equal(doc.xpath("Default[@Extension='xml']").size, 1) 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /test/content_type/tc_override.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | class TestOverride < Test::Unit::TestCase 3 | 4 | def test_content_type_restriction 5 | assert_raise(ArgumentError, "requires known content type") { Axlsx::Override.new :ContentType=>"asdf" } 6 | end 7 | 8 | def test_to_xml 9 | type = Axlsx::Override.new :PartName=>"somechart.xml", :ContentType=>Axlsx::CHART_CT 10 | doc = Nokogiri::XML(type.to_xml_string) 11 | assert_equal(doc.xpath("Override[@ContentType='#{Axlsx::CHART_CT}']").size, 1) 12 | assert_equal(doc.xpath("Override[@PartName='somechart.xml']").size, 1) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /test/doc_props/tc_app.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestApp < Test::Unit::TestCase 4 | def setup 5 | options = { 6 | :'Template' => 'Foo.xlt', 7 | :'Manager' => 'Penny', 8 | :'Company' => "Bob's Repair", 9 | :'Pages' => 1, 10 | :'Words' => 2, 11 | :'Characters' => 7, 12 | :'PresentationFormat' => 'any', 13 | :'Lines' => 1, 14 | :'Paragraphs' => 1, 15 | :'Slides' => 4, 16 | :'Notes' => 1, 17 | :'TotalTime' => 2, 18 | :'HidddenSlides' => 3, 19 | :'MMClips' => 10, 20 | :'ScaleCrop' => true, 21 | :'LinksUpToDate' => true, 22 | :'CharactersWithSpaces' => 9, 23 | :'SharedDoc' => false, 24 | :'HyperlinkBase' => 'foo', 25 | :'HyperlInksChanged' => false, 26 | :'Application' => 'axlsx', 27 | :'AppVersion' => '1.1.5', 28 | :'DocSecurity' => 0 29 | } 30 | 31 | @app = Axlsx::App.new options 32 | 33 | end 34 | def test_valid_document 35 | schema = Nokogiri::XML::Schema(File.open(Axlsx::APP_XSD)) 36 | doc = Nokogiri::XML(@app.to_xml_string) 37 | errors = [] 38 | schema.validate(doc).each do |error| 39 | errors << error 40 | end 41 | assert_equal(errors.size, 0, "app.xml invalid" + errors.map{ |e| e.message }.to_s) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/doc_props/tc_core.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestCore < Test::Unit::TestCase 4 | 5 | def setup 6 | @core = Axlsx::Core.new 7 | # could still see some false positives if the second changes between the next two calls 8 | @time = Time.now.strftime('%Y-%m-%dT%H:%M:%SZ') 9 | @doc = Nokogiri::XML(@core.to_xml_string) 10 | end 11 | 12 | def test_valid_document 13 | schema = Nokogiri::XML::Schema(File.open(Axlsx::CORE_XSD)) 14 | errors = [] 15 | schema.validate(@doc).each do |error| 16 | puts error.message 17 | errors << error 18 | end 19 | assert_equal(errors.size, 0, "core.xml Invalid" + errors.map{ |e| e.message }.to_s) 20 | end 21 | 22 | def test_populates_created 23 | assert_equal(@doc.xpath('//dcterms:created').text, @time, "dcterms:created incorrect") 24 | end 25 | 26 | def test_created_as_option 27 | time = Time.utc(2013, 1, 1, 12, 00) 28 | c = Axlsx::Core.new :created => time 29 | doc = Nokogiri::XML(c.to_xml_string) 30 | assert_equal(doc.xpath('//dcterms:created').text, time.xmlschema, "dcterms:created incorrect") 31 | end 32 | 33 | def test_populates_default_name 34 | assert_equal(@doc.xpath('//dc:creator').text, "axlsx", "Default name not populated") 35 | end 36 | 37 | def test_creator_as_option 38 | c = Axlsx::Core.new :creator => "some guy" 39 | doc = Nokogiri::XML(c.to_xml_string) 40 | assert(doc.xpath('//dc:creator').text == "some guy") 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /test/drawing/tc_area_chart.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestAreaChart < Test::Unit::TestCase 4 | 5 | def setup 6 | @p = Axlsx::Package.new 7 | ws = @p.workbook.add_worksheet 8 | @row = ws.add_row ["one", 1, Time.now] 9 | @chart = ws.add_chart Axlsx::AreaChart, :title => "fishery" 10 | end 11 | 12 | def teardown 13 | end 14 | 15 | def test_initialization 16 | assert_equal(@chart.grouping, :standard, "grouping defualt incorrect") 17 | assert_equal(@chart.series_type, Axlsx::AreaSeries, "series type incorrect") 18 | assert(@chart.cat_axis.is_a?(Axlsx::CatAxis), "category axis not created") 19 | assert(@chart.val_axis.is_a?(Axlsx::ValAxis), "value access not created") 20 | end 21 | 22 | def test_grouping 23 | assert_raise(ArgumentError, "require valid grouping") { @chart.grouping = :inverted } 24 | assert_nothing_raised("allow valid grouping") { @chart.grouping = :stacked } 25 | assert(@chart.grouping == :stacked) 26 | end 27 | 28 | def test_to_xml 29 | schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) 30 | doc = Nokogiri::XML(@chart.to_xml_string) 31 | errors = [] 32 | schema.validate(doc).each do |error| 33 | errors.push error 34 | puts error.message 35 | end 36 | assert(errors.empty?, "error free validation") 37 | end 38 | 39 | end 40 | -------------------------------------------------------------------------------- /test/drawing/tc_axes.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestAxes < Test::Unit::TestCase 4 | def test_constructor_requires_cat_axis_first 5 | assert_raise(ArgumentError) { Axlsx::Axes.new(:val_axis => Axlsx::ValAxis, :cat_axis => Axlsx::CatAxis) } 6 | assert_nothing_raised { Axlsx::Axes.new(:cat_axis => Axlsx::CatAxis, :val_axis => Axlsx::ValAxis) } 7 | end 8 | end -------------------------------------------------------------------------------- /test/drawing/tc_bar_series.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestBarSeries < Test::Unit::TestCase 4 | 5 | def setup 6 | p = Axlsx::Package.new 7 | @ws = p.workbook.add_worksheet :name=>"hmmm" 8 | @chart = @ws.add_chart Axlsx::Bar3DChart, :title => "fishery" 9 | @series = @chart.add_series :data=>[0,1,2], :labels=>["zero", "one", "two"], :title=>"bob", :colors => ['FF0000', '00FF00', '0000FF'], :shape => :cone 10 | end 11 | 12 | def test_initialize 13 | assert_equal(@series.title.text, "bob", "series title has been applied") 14 | assert_equal(@series.data.class, Axlsx::NumDataSource, "data option applied") 15 | assert_equal(@series.shape, :cone, "series shape has been applied") 16 | assert(@series.data.is_a?(Axlsx::NumDataSource)) 17 | assert(@series.labels.is_a?(Axlsx::AxDataSource)) 18 | end 19 | 20 | def test_colors 21 | assert_equal(@series.colors.size, 3) 22 | end 23 | 24 | def test_shape 25 | assert_raise(ArgumentError, "require valid shape") { @series.shape = :teardropt } 26 | assert_nothing_raised("allow valid shape") { @series.shape = :box } 27 | assert(@series.shape == :box) 28 | end 29 | 30 | def test_to_xml_string 31 | doc = Nokogiri::XML(@chart.to_xml_string) 32 | @series.colors.each_with_index do |color, index| 33 | assert_equal(doc.xpath("//c:dPt/c:idx[@val='#{index}']").size,1) 34 | assert_equal(doc.xpath("//c:dPt/c:spPr/a:solidFill/a:srgbClr[@val='#{@series.colors[index]}']").size,1) 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/drawing/tc_bubble_chart.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestBubbleChart < Test::Unit::TestCase 4 | def setup 5 | @p = Axlsx::Package.new 6 | @chart = nil 7 | @p.workbook.add_worksheet do |sheet| 8 | sheet.add_row ["First", 1, 5, 7, 9] 9 | sheet.add_row ["", 1, 25, 49, 81] 10 | sheet.add_row ["", 1, 42, 60, 75] 11 | sheet.add_row ["Second", 5, 2, 14, 9] 12 | sheet.add_row ["", 5, 10, 15, 20] 13 | sheet.add_row ["", 5, 28, 92, 13] 14 | sheet.add_chart(Axlsx::BubbleChart, :title => "example: Bubble Chart") do |chart| 15 | chart.start_at 0, 4 16 | chart.end_at 10, 19 17 | chart.add_series :xData => sheet["B1:E1"], :yData => sheet["B2:E2"], :bubbleSize => sheet["B3:E3"], :title => sheet["A1"] 18 | chart.add_series :xData => sheet["B4:E4"], :yData => sheet["B5:E5"], :bubbleSize => sheet["B6:E6"], :title => sheet["A3"] 19 | @chart = chart 20 | end 21 | end 22 | end 23 | 24 | def teardown 25 | end 26 | 27 | def test_initialization 28 | assert_equal(@chart.series_type, Axlsx::BubbleSeries, "series type incorrect") 29 | assert(@chart.xValAxis.is_a?(Axlsx::ValAxis), "independant value axis not created") 30 | assert(@chart.yValAxis.is_a?(Axlsx::ValAxis), "dependant value axis not created") 31 | end 32 | 33 | def test_to_xml_string 34 | schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) 35 | doc = Nokogiri::XML(@chart.to_xml_string) 36 | errors = [] 37 | schema.validate(doc).each do |error| 38 | errors.push error 39 | puts error.message 40 | end 41 | assert(errors.empty?, "error free validation") 42 | end 43 | 44 | end 45 | -------------------------------------------------------------------------------- /test/drawing/tc_bubble_series.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestBubbleSeries < Test::Unit::TestCase 4 | 5 | def setup 6 | p = Axlsx::Package.new 7 | @ws = p.workbook.add_worksheet :name=>"hmmm" 8 | @chart = @ws.add_chart Axlsx::BubbleChart, :title => "Bubble Chart" 9 | @series = @chart.add_series :xData=>[1,2,4], :yData=>[1,3,9], :bubbleSize=>[1,5,7], :title=>"GDP", :color => 'FF0000' 10 | end 11 | 12 | def test_initialize 13 | assert_equal(@series.title.text, "GDP", "series title has been applied") 14 | end 15 | 16 | def test_to_xml_string 17 | doc = Nokogiri::XML(@chart.to_xml_string) 18 | assert_equal(doc.xpath("//a:srgbClr[@val='#{@series.color}']").size,2) 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /test/drawing/tc_cat_axis.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestCatAxis < Test::Unit::TestCase 4 | def setup 5 | @axis = Axlsx::CatAxis.new 6 | end 7 | def teardown 8 | end 9 | 10 | def test_initialization 11 | assert_equal(@axis.auto, 1, "axis auto default incorrect") 12 | assert_equal(@axis.lbl_algn, :ctr, "label align default incorrect") 13 | assert_equal(@axis.lbl_offset, "100", "label offset default incorrect") 14 | end 15 | 16 | def test_auto 17 | assert_raise(ArgumentError, "requires valid auto") { @axis.auto = :nowhere } 18 | assert_nothing_raised("accepts valid auto") { @axis.auto = false } 19 | end 20 | 21 | def test_lbl_algn 22 | assert_raise(ArgumentError, "requires valid label alignment") { @axis.lbl_algn = :nowhere } 23 | assert_nothing_raised("accepts valid label alignment") { @axis.lbl_algn = :r } 24 | end 25 | 26 | def test_lbl_offset 27 | assert_raise(ArgumentError, "requires valid label offset") { @axis.lbl_offset = 'foo' } 28 | assert_nothing_raised("accepts valid label offset") { @axis.lbl_offset = "20" } 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /test/drawing/tc_cat_axis_data.rb: -------------------------------------------------------------------------------- 1 | # require 'tc_helper.rb' 2 | 3 | # class TestCatAxisData < Test::Unit::TestCase 4 | 5 | # def setup 6 | # p = Axlsx::Package.new 7 | # @ws = p.workbook.add_worksheet 8 | # @chart = @ws.drawing.add_chart Axlsx::Bar3DChart 9 | # @series = @chart.add_series :labels=>["zero", "one", "two"] 10 | # end 11 | 12 | # def test_initialize 13 | # assert(@series.labels.is_a?Axlsx::SimpleTypedList) 14 | # assert_equal(@series.labels, ["zero", "one", "two"]) 15 | # end 16 | 17 | # def test_to_xml_string 18 | # doc = Nokogiri::XML(@chart.to_xml_string) 19 | # assert_equal(doc.xpath("//c:cat/c:strRef/c:f").size,1) 20 | # assert_equal(doc.xpath("//c:strCache/c:ptCount[@val='#{@series.labels.size}']").size,1) 21 | # @series.labels.each_with_index do |label, index| 22 | # assert_equal(doc.xpath("//c:strCache/c:pt[@idx='#{index}']").size,1) 23 | # assert_equal(doc.xpath("//c:strCache/c:pt/c:v[text()='#{label}']").size,1) 24 | # end 25 | # end 26 | 27 | # end 28 | -------------------------------------------------------------------------------- /test/drawing/tc_data_source.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestNumDataSource < Test::Unit::TestCase 4 | 5 | def setup 6 | @data_source = Axlsx::NumDataSource.new :data => ["1", "2", "3"] 7 | end 8 | 9 | def test_tag_name 10 | assert_raise(ArgumentError) { @data_source.tag_name = :zVal } 11 | assert_nothing_raised { @data_source.tag_name = :yVal } 12 | assert_nothing_raised { @data_source.tag_name = :bubbleSize } 13 | end 14 | 15 | def test_to_xml_string_strLit 16 | str = '' 17 | str << '' 18 | str << @data_source.to_xml_string 19 | doc = Nokogiri::XML(str) 20 | assert_equal(doc.xpath("//c:val").size, 1) 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /test/drawing/tc_graphic_frame.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestGraphicFrame < Test::Unit::TestCase 4 | def setup 5 | p = Axlsx::Package.new 6 | @ws = p.workbook.add_worksheet 7 | @chart = @ws.add_chart Axlsx::Chart 8 | @frame = @chart.graphic_frame 9 | end 10 | 11 | def teardown 12 | end 13 | 14 | def test_initialization 15 | assert(@frame.anchor.is_a?(Axlsx::TwoCellAnchor)) 16 | assert_equal(@frame.chart, @chart) 17 | end 18 | 19 | def test_rId 20 | assert_equal @ws.drawing.relationships.for(@chart).Id, @frame.rId 21 | end 22 | 23 | def test_to_xml_has_correct_rId 24 | doc = Nokogiri::XML(@frame.to_xml_string) 25 | assert_equal @frame.rId, doc.xpath("//c:chart", doc.collect_namespaces).first["r:id"] 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /test/drawing/tc_hyperlink.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestHyperlink < Test::Unit::TestCase 4 | 5 | def setup 6 | @p = Axlsx::Package.new 7 | ws = @p.workbook.add_worksheet 8 | @test_img = File.dirname(__FILE__) + "/../../examples/image1.jpeg" 9 | @image = ws.add_image :image_src => @test_img, :hyperlink => "http://axlsx.blogspot.com" 10 | @hyperlink = @image.hyperlink 11 | end 12 | 13 | def teardown 14 | end 15 | 16 | 17 | def test_href 18 | assert_nothing_raised { @hyperlink.href = "http://axlsx.blogspot.com" } 19 | assert_equal(@hyperlink.href, "http://axlsx.blogspot.com") 20 | end 21 | 22 | def test_tgtFrame 23 | assert_nothing_raised { @hyperlink.tgtFrame = "http://axlsx.blogspot.com" } 24 | assert_equal(@hyperlink.tgtFrame, "http://axlsx.blogspot.com") 25 | end 26 | 27 | def test_tooltip 28 | assert_nothing_raised { @hyperlink.tooltip = "http://axlsx.blogspot.com" } 29 | assert_equal(@hyperlink.tooltip, "http://axlsx.blogspot.com") 30 | end 31 | 32 | def test_invalidUrl 33 | assert_nothing_raised { @hyperlink.invalidUrl = "http://axlsx.blogspot.com" } 34 | assert_equal(@hyperlink.invalidUrl, "http://axlsx.blogspot.com") 35 | end 36 | 37 | def test_action 38 | assert_nothing_raised { @hyperlink.action = "flee" } 39 | assert_equal(@hyperlink.action, "flee") 40 | end 41 | 42 | def test_endSnd 43 | assert_nothing_raised { @hyperlink.endSnd = "true" } 44 | assert_raise(ArgumentError) {@hyperlink.endSnd = "bob"} 45 | assert_equal(@hyperlink.endSnd, "true") 46 | end 47 | 48 | def test_highlightClick 49 | assert_nothing_raised { @hyperlink.highlightClick = false } 50 | assert_raise(ArgumentError) {@hyperlink.highlightClick = "bob"} 51 | assert_equal(@hyperlink.highlightClick, false ) 52 | end 53 | 54 | def test_history 55 | assert_nothing_raised { @hyperlink.history = false } 56 | assert_raise(ArgumentError) {@hyperlink.history = "bob"} 57 | assert_equal(@hyperlink.history, false ) 58 | end 59 | 60 | def test_to_xml_string 61 | doc = Nokogiri::XML(@p.workbook.worksheets.first.drawing.to_xml_string) 62 | assert(doc.xpath("//a:hlinkClick")) 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /test/drawing/tc_line_3d_chart.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestLine3DChart < Test::Unit::TestCase 4 | 5 | def setup 6 | @p = Axlsx::Package.new 7 | ws = @p.workbook.add_worksheet 8 | @row = ws.add_row ["one", 1, Time.now] 9 | @chart = ws.add_chart Axlsx::Line3DChart, :title => "fishery" 10 | end 11 | 12 | def teardown 13 | end 14 | 15 | def test_initialization 16 | assert_equal(@chart.grouping, :standard, "grouping defualt incorrect") 17 | assert_equal(@chart.series_type, Axlsx::LineSeries, "series type incorrect") 18 | assert(@chart.catAxis.is_a?(Axlsx::CatAxis), "category axis not created") 19 | assert(@chart.valAxis.is_a?(Axlsx::ValAxis), "value access not created") 20 | assert(@chart.serAxis.is_a?(Axlsx::SerAxis), "value access not created") 21 | end 22 | 23 | def test_grouping 24 | assert_raise(ArgumentError, "require valid grouping") { @chart.grouping = :inverted } 25 | assert_nothing_raised("allow valid grouping") { @chart.grouping = :stacked } 26 | assert(@chart.grouping == :stacked) 27 | end 28 | 29 | def test_gapDepth 30 | assert_raise(ArgumentError, "require valid gapDepth") { @chart.gapDepth = 200 } 31 | assert_nothing_raised("allow valid gapDepth") { @chart.gapDepth = "200%" } 32 | assert(@chart.gapDepth == "200%") 33 | end 34 | 35 | 36 | def test_to_xml 37 | schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) 38 | doc = Nokogiri::XML(@chart.to_xml_string) 39 | errors = [] 40 | schema.validate(doc).each do |error| 41 | errors.push error 42 | puts error.message 43 | end 44 | assert(errors.empty?, "error free validation") 45 | end 46 | 47 | end 48 | -------------------------------------------------------------------------------- /test/drawing/tc_line_chart.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestLineChart < Test::Unit::TestCase 4 | 5 | def setup 6 | @p = Axlsx::Package.new 7 | ws = @p.workbook.add_worksheet 8 | @row = ws.add_row ["one", 1, Time.now] 9 | @chart = ws.add_chart Axlsx::LineChart, :title => "fishery" 10 | end 11 | 12 | def teardown 13 | end 14 | 15 | def test_initialization 16 | assert_equal(@chart.grouping, :standard, "grouping defualt incorrect") 17 | assert_equal(@chart.series_type, Axlsx::LineSeries, "series type incorrect") 18 | assert(@chart.cat_axis.is_a?(Axlsx::CatAxis), "category axis not created") 19 | assert(@chart.val_axis.is_a?(Axlsx::ValAxis), "value access not created") 20 | end 21 | 22 | def test_grouping 23 | assert_raise(ArgumentError, "require valid grouping") { @chart.grouping = :inverted } 24 | assert_nothing_raised("allow valid grouping") { @chart.grouping = :stacked } 25 | assert(@chart.grouping == :stacked) 26 | end 27 | 28 | def test_to_xml 29 | schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) 30 | doc = Nokogiri::XML(@chart.to_xml_string) 31 | errors = [] 32 | schema.validate(doc).each do |error| 33 | errors.push error 34 | puts error.message 35 | end 36 | assert(errors.empty?, "error free validation") 37 | end 38 | 39 | end 40 | -------------------------------------------------------------------------------- /test/drawing/tc_marker.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestMarker < Test::Unit::TestCase 4 | def setup 5 | @marker = Axlsx::Marker.new 6 | end 7 | 8 | def teardown 9 | end 10 | 11 | def test_initialization 12 | assert(@marker.col == 0) 13 | assert(@marker.colOff == 0) 14 | assert(@marker.row == 0) 15 | assert(@marker.rowOff == 0) 16 | end 17 | 18 | def test_col 19 | assert_raise(ArgumentError) { @marker.col = -1} 20 | assert_nothing_raised {@marker.col = 10} 21 | end 22 | 23 | def test_colOff 24 | assert_raise(ArgumentError) { @marker.colOff = "1"} 25 | assert_nothing_raised {@marker.colOff = -10} 26 | end 27 | 28 | def test_row 29 | assert_raise(ArgumentError) { @marker.row = -1} 30 | assert_nothing_raised {@marker.row = 10} 31 | end 32 | 33 | def test_rowOff 34 | assert_raise(ArgumentError) { @marker.rowOff = "1"} 35 | assert_nothing_raised {@marker.rowOff = -10} 36 | end 37 | 38 | def test_coord 39 | @marker.coord 5, 10 40 | assert_equal(@marker.col, 5) 41 | assert_equal(@marker.row, 10) 42 | end 43 | 44 | end 45 | -------------------------------------------------------------------------------- /test/drawing/tc_named_axis_data.rb: -------------------------------------------------------------------------------- 1 | # require 'tc_helper.rb' 2 | 3 | # class TestNamedAxisData < Test::Unit::TestCase 4 | 5 | # def setup 6 | # p = Axlsx::Package.new 7 | # @ws = p.workbook.add_worksheet 8 | # @chart = @ws.drawing.add_chart Axlsx::Line3DChart 9 | # @series = @chart.add_series :data=>[0,1,2] 10 | # end 11 | 12 | # def test_initialize 13 | # assert(@series.data.is_a?Axlsx::SimpleTypedList) 14 | # assert_equal(@series.data, [0,1,2]) 15 | # end 16 | 17 | # def test_to_xml_string 18 | # doc = Nokogiri::XML(@chart.to_xml_string) 19 | # assert_equal(doc.xpath("//c:val/c:numRef/c:f").size,1) 20 | # assert_equal(doc.xpath("//c:numCache/c:ptCount[@val='#{@series.data.size}']").size,1) 21 | # @series.data.each_with_index do |datum, index| 22 | # assert_equal(doc.xpath("//c:numCache/c:pt[@idx='#{index}']").size,1) 23 | # assert_equal(doc.xpath("//c:numCache/c:pt/c:v[text()='#{datum}']").size,1) 24 | # end 25 | # end 26 | 27 | # end 28 | -------------------------------------------------------------------------------- /test/drawing/tc_num_data.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestNumData < Test::Unit::TestCase 4 | 5 | def setup 6 | @num_data = Axlsx::NumData.new :data => [1, 2, 3] 7 | end 8 | 9 | def test_initialize 10 | assert_equal(@num_data.format_code, "General") 11 | end 12 | 13 | def test_formula_based_cell 14 | 15 | end 16 | 17 | def test_format_code 18 | assert_raise(ArgumentError) {@num_data.format_code = 7} 19 | assert_nothing_raised {@num_data.format_code = 'foo_bar'} 20 | end 21 | 22 | def test_to_xml_string 23 | str = '' 24 | str << '' 25 | str << @num_data.to_xml_string 26 | doc = Nokogiri::XML(str) 27 | assert_equal(doc.xpath("//c:numLit/c:ptCount[@val=3]").size, 1) 28 | assert_equal(doc.xpath("//c:numLit/c:pt/c:v[text()='1']").size, 1) 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /test/drawing/tc_num_val.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestNumVal < Test::Unit::TestCase 4 | 5 | def setup 6 | @num_val = Axlsx::NumVal.new :v => 1 7 | end 8 | 9 | def test_initialize 10 | assert_equal(@num_val.format_code, "General") 11 | assert_equal(@num_val.v, "1") 12 | end 13 | 14 | def test_format_code 15 | assert_raise(ArgumentError) {@num_val.format_code = 7} 16 | assert_nothing_raised {@num_val.format_code = 'foo_bar'} 17 | end 18 | 19 | def test_to_xml_string 20 | str = '' 21 | str << '' 22 | str << @num_val.to_xml_string(0) 23 | doc = Nokogiri::XML(str) 24 | # lets see if this works? 25 | assert_equal(doc.xpath("//c:pt/c:v[text()='1']").size, 1) 26 | 27 | end 28 | 29 | end 30 | -------------------------------------------------------------------------------- /test/drawing/tc_one_cell_anchor.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestOneCellAnchor < Test::Unit::TestCase 4 | 5 | def setup 6 | @p = Axlsx::Package.new 7 | @ws = @p.workbook.add_worksheet 8 | @test_img = File.dirname(__FILE__) + "/../../examples/image1.jpeg" 9 | @image = @ws.add_image :image_src => @test_img 10 | @anchor = @image.anchor 11 | end 12 | 13 | def teardown 14 | end 15 | 16 | def test_initialization 17 | assert(@anchor.from.col == 0) 18 | assert(@anchor.from.row == 0) 19 | assert(@anchor.width == 0) 20 | assert(@anchor.height == 0) 21 | end 22 | 23 | def test_from 24 | assert(@anchor.from.is_a?(Axlsx::Marker)) 25 | end 26 | 27 | def test_object 28 | assert(@anchor.object.is_a?(Axlsx::Pic)) 29 | end 30 | 31 | def test_index 32 | assert_equal(@anchor.index, @anchor.drawing.anchors.index(@anchor)) 33 | end 34 | 35 | def test_width 36 | assert_raise(ArgumentError) { @anchor.width = "a" } 37 | assert_nothing_raised { @anchor.width = 600 } 38 | assert_equal(@anchor.width, 600) 39 | end 40 | 41 | def test_height 42 | assert_raise(ArgumentError) { @anchor.height = "a" } 43 | assert_nothing_raised { @anchor.height = 400 } 44 | assert_equal(400, @anchor.height) 45 | end 46 | 47 | def test_ext 48 | ext = @anchor.send(:ext) 49 | assert_equal(ext[:cx], (@anchor.width * 914400 / 96)) 50 | assert_equal(ext[:cy], (@anchor.height * 914400 / 96)) 51 | end 52 | 53 | def test_options 54 | assert_raise(ArgumentError, 'invalid start_at') { @ws.add_image :image_src=>@test_img, :start_at=>[1] } 55 | i = @ws.add_image :image_src=>@test_img, :start_at => [1,2], :width=>100, :height=>200, :name=>"someimage", :descr=>"a neat image" 56 | 57 | assert_equal("a neat image", i.descr) 58 | assert_equal("someimage", i.name) 59 | assert_equal(200, i.height) 60 | assert_equal(100, i.width) 61 | assert_equal(1, i.anchor.from.col) 62 | assert_equal(2, i.anchor.from.row) 63 | assert_equal(@test_img, i.image_src) 64 | end 65 | 66 | end 67 | -------------------------------------------------------------------------------- /test/drawing/tc_pie_3D_chart.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestPie3DChart < Test::Unit::TestCase 4 | 5 | def setup 6 | p = Axlsx::Package.new 7 | ws = p.workbook.add_worksheet 8 | @row = ws.add_row ["one", 1, Time.now] 9 | @chart = ws.add_chart Axlsx::Pie3DChart, :title => "fishery" 10 | end 11 | 12 | def teardown 13 | end 14 | 15 | def test_initialization 16 | assert_equal(@chart.view_3D.rot_x, 30, "view 3d default rot_x incorrect") 17 | assert_equal(@chart.view_3D.perspective, 30, "view_3d default perspective incorrect") 18 | assert_equal(@chart.series_type, Axlsx::PieSeries, "series type incorrect") 19 | end 20 | 21 | def test_to_xml 22 | schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) 23 | doc = Nokogiri::XML(@chart.to_xml_string) 24 | errors = schema.validate(doc).map {|error| puts error.message; error } 25 | assert(errors.empty?, "error free validation") 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /test/drawing/tc_pie_series.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestPieSeries < Test::Unit::TestCase 4 | 5 | def setup 6 | p = Axlsx::Package.new 7 | @ws = p.workbook.add_worksheet :name=>"hmmm" 8 | chart = @ws.add_chart Axlsx::Pie3DChart, :title => "fishery" 9 | @series = chart.add_series :data=>[0,1,2], :labels=>["zero", "one", "two"], :title=>"bob", :colors => ["FF0000", "00FF00", "0000FF"] 10 | end 11 | 12 | def test_initialize 13 | assert_equal(@series.title.text, "bob", "series title has been applied") 14 | assert_equal(@series.labels.class, Axlsx::AxDataSource) 15 | assert_equal(@series.data.class, Axlsx::NumDataSource) 16 | assert_equal(@series.explosion, nil, "series shape has been applied") 17 | end 18 | 19 | def test_explosion 20 | assert_raise(ArgumentError, "require valid explosion") { @series.explosion = :lots } 21 | assert_nothing_raised("allow valid explosion") { @series.explosion = 20 } 22 | assert(@series.explosion == 20) 23 | end 24 | 25 | def test_to_xml_string 26 | doc = Nokogiri::XML(@series.to_xml_string) 27 | assert(doc.xpath("//srgbClr[@val='#{@series.colors[0]}']")) 28 | 29 | end 30 | #TODO test unique serialization parts 31 | 32 | end 33 | -------------------------------------------------------------------------------- /test/drawing/tc_scaling.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestScaling < Test::Unit::TestCase 4 | def setup 5 | @scaling = Axlsx::Scaling.new 6 | end 7 | 8 | def teardown 9 | end 10 | 11 | def test_initialization 12 | assert(@scaling.orientation == :minMax) 13 | end 14 | 15 | def test_logBase 16 | assert_raise(ArgumentError) { @scaling.logBase = 1} 17 | assert_nothing_raised {@scaling.logBase = 10} 18 | end 19 | 20 | def test_orientation 21 | assert_raise(ArgumentError) { @scaling.orientation = "1"} 22 | assert_nothing_raised {@scaling.orientation = :maxMin} 23 | end 24 | 25 | 26 | def test_max 27 | assert_raise(ArgumentError) { @scaling.max = 1} 28 | assert_nothing_raised {@scaling.max = 10.5} 29 | end 30 | 31 | def test_min 32 | assert_raise(ArgumentError) { @scaling.min = 1} 33 | assert_nothing_raised {@scaling.min = 10.5} 34 | end 35 | 36 | end 37 | -------------------------------------------------------------------------------- /test/drawing/tc_scatter_chart.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestScatterChart < Test::Unit::TestCase 4 | def setup 5 | @p = Axlsx::Package.new 6 | @chart = nil 7 | @p.workbook.add_worksheet do |sheet| 8 | sheet.add_row ["First", 1, 5, 7, 9] 9 | sheet.add_row ["", 1, 25, 49, 81] 10 | sheet.add_row ["Second", 5, 2, 14, 9] 11 | sheet.add_row ["", 5, 10, 15, 20] 12 | sheet.add_chart(Axlsx::ScatterChart, :title => "example 7: Scatter Chart") do |chart| 13 | chart.start_at 0, 4 14 | chart.end_at 10, 19 15 | chart.add_series :xData => sheet["B1:E1"], :yData => sheet["B2:E2"], :title => sheet["A1"] 16 | chart.add_series :xData => sheet["B3:E3"], :yData => sheet["B4:E4"], :title => sheet["A3"] 17 | @chart = chart 18 | end 19 | end 20 | end 21 | 22 | def teardown 23 | end 24 | 25 | def test_scatter_style 26 | @chart.scatterStyle = :marker 27 | assert(@chart.scatterStyle == :marker) 28 | assert_raise(ArgumentError) { @chart.scatterStyle = :buckshot } 29 | end 30 | def test_initialization 31 | assert_equal(@chart.scatterStyle, :lineMarker, "scatterStyle defualt incorrect") 32 | assert_equal(@chart.series_type, Axlsx::ScatterSeries, "series type incorrect") 33 | assert(@chart.xValAxis.is_a?(Axlsx::ValAxis), "independant value axis not created") 34 | assert(@chart.yValAxis.is_a?(Axlsx::ValAxis), "dependant value axis not created") 35 | end 36 | 37 | def test_to_xml_string 38 | schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) 39 | doc = Nokogiri::XML(@chart.to_xml_string) 40 | errors = [] 41 | schema.validate(doc).each do |error| 42 | errors.push error 43 | puts error.message 44 | end 45 | assert(errors.empty?, "error free validation") 46 | end 47 | 48 | end 49 | -------------------------------------------------------------------------------- /test/drawing/tc_ser_axis.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestSerAxis < Test::Unit::TestCase 4 | def setup 5 | @axis = Axlsx::SerAxis.new 6 | end 7 | 8 | def teardown 9 | end 10 | 11 | def test_options 12 | a = Axlsx::SerAxis.new(:tick_lbl_skip => 9, :tick_mark_skip => 7) 13 | assert_equal(a.tick_lbl_skip, 9) 14 | assert_equal(a.tick_mark_skip, 7) 15 | end 16 | 17 | 18 | def test_tick_lbl_skip 19 | assert_raise(ArgumentError, "requires valid tick_lbl_skip") { @axis.tick_lbl_skip = -1 } 20 | assert_nothing_raised("accepts valid tick_lbl_skip") { @axis.tick_lbl_skip = 1 } 21 | assert_equal(@axis.tick_lbl_skip, 1) 22 | end 23 | 24 | 25 | def test_tick_mark_skip 26 | assert_raise(ArgumentError, "requires valid tick_mark_skip") { @axis.tick_mark_skip = :my_eyes } 27 | assert_nothing_raised("accepts valid tick_mark_skip") { @axis.tick_mark_skip = 2 } 28 | assert_equal(@axis.tick_mark_skip, 2) 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /test/drawing/tc_series.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestSeries < Test::Unit::TestCase 4 | 5 | def setup 6 | p = Axlsx::Package.new 7 | @ws = p.workbook.add_worksheet :name=>"hmmm" 8 | chart = @ws.add_chart Axlsx::Chart, :title => "fishery" 9 | @series = chart.add_series :title=>"bob" 10 | end 11 | 12 | def test_initialize 13 | assert_equal(@series.title.text, "bob", "series title has been applied") 14 | assert_equal(@series.order, @series.index, "order is index by default") 15 | assert_equal(@series.index, @series.chart.series.index(@series), "index is applied") 16 | end 17 | 18 | def test_order 19 | @series.order = 2 20 | assert_equal(@series.order, 2) 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /test/drawing/tc_series_title.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestSeriesTitle < Test::Unit::TestCase 4 | def setup 5 | @p = Axlsx::Package.new 6 | ws = @p.workbook.add_worksheet 7 | @row = ws.add_row ["one", 1, Time.now] 8 | @title = Axlsx::SeriesTitle.new 9 | @chart = ws.add_chart Axlsx::Bar3DChart 10 | end 11 | 12 | def teardown 13 | end 14 | 15 | def test_initialization 16 | assert(@title.text == "") 17 | assert(@title.cell == nil) 18 | end 19 | 20 | def test_text 21 | assert_raise(ArgumentError, "text must be a string") { @title.text = 123 } 22 | @title.cell = @row.cells.first 23 | @title.text = "bob" 24 | assert(@title.cell == nil, "setting title with text clears the cell") 25 | end 26 | 27 | def test_cell 28 | assert_raise(ArgumentError, "cell must be a Cell") { @title.cell = "123" } 29 | @title.cell = @row.cells.first 30 | assert(@title.text == "one") 31 | end 32 | 33 | end 34 | -------------------------------------------------------------------------------- /test/drawing/tc_str_data.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestStrData < Test::Unit::TestCase 4 | 5 | def setup 6 | @str_data = Axlsx::StrData.new :data => ["1", "2", "3"] 7 | end 8 | 9 | def test_to_xml_string_strLit 10 | str = '' 11 | str << '' 12 | str << @str_data.to_xml_string 13 | doc = Nokogiri::XML(str) 14 | assert_equal(doc.xpath("//c:strLit/c:ptCount[@val=3]").size, 1) 15 | assert_equal(doc.xpath("//c:strLit/c:pt/c:v[text()='1']").size, 1) 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /test/drawing/tc_str_val.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestStrVal < Test::Unit::TestCase 4 | 5 | def setup 6 | @str_val = Axlsx::StrVal.new :v => "1" 7 | @str_val_with_special_characters = Axlsx::StrVal.new :v => "a & b " 8 | end 9 | 10 | def test_initialize 11 | assert_equal(@str_val.v, "1") 12 | end 13 | 14 | def test_to_xml_string 15 | str = '' 16 | str << '' 17 | str << @str_val.to_xml_string(0) 18 | doc = Nokogiri::XML(str) 19 | assert_equal(doc.xpath("//c:pt/c:v[text()='1']").size, 1) 20 | end 21 | 22 | def test_to_xml_string_special_characters 23 | str = '' 24 | str << '' 25 | str << @str_val_with_special_characters.to_xml_string(0) 26 | doc = Nokogiri::XML(str) 27 | assert_equal(doc.xpath("//c:pt/c:v[text()='a & b ']").size, 1) 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /test/drawing/tc_title.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../" 2 | 3 | require 'tc_helper.rb' 4 | 5 | class TestTitle < Test::Unit::TestCase 6 | def setup 7 | @p = Axlsx::Package.new 8 | ws = @p.workbook.add_worksheet 9 | @row = ws.add_row ["one", 1, Time.now] 10 | @title = Axlsx::Title.new 11 | @chart = ws.add_chart Axlsx::Bar3DChart 12 | end 13 | 14 | def teardown 15 | end 16 | 17 | def test_initialization 18 | assert(@title.text == "") 19 | assert(@title.cell == nil) 20 | end 21 | 22 | def test_initialize_title_size 23 | title = Axlsx::Title.new 'bob', 90 24 | assert_equal "90", title.text_size 25 | end 26 | 27 | def test_text 28 | assert_raise(ArgumentError, "text must be a string") { @title.text = 123 } 29 | @title.cell = @row.cells.first 30 | @title.text = "bob" 31 | assert(@title.cell == nil, "setting title with text clears the cell") 32 | end 33 | 34 | def test_cell 35 | assert_raise(ArgumentError, "cell must be a Cell") { @title.cell = "123" } 36 | @title.cell = @row.cells.first 37 | assert(@title.text == "one") 38 | end 39 | 40 | def test_to_xml_string_text 41 | @chart.title.text = 'foo' 42 | doc = Nokogiri::XML(@chart.to_xml_string) 43 | assert_equal(1, doc.xpath('//c:rich').size) 44 | assert_equal(1, doc.xpath("//a:t[text()='foo']").size) 45 | end 46 | 47 | def test_to_xml_string_cell 48 | @chart.title.cell = @row.cells.first 49 | doc = Nokogiri::XML(@chart.to_xml_string) 50 | assert_equal(1, doc.xpath('//c:strCache').size) 51 | assert_equal(1, doc.xpath('//c:v[text()="one"]').size) 52 | end 53 | 54 | end 55 | -------------------------------------------------------------------------------- /test/drawing/tc_two_cell_anchor.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestTwoCellAnchor < Test::Unit::TestCase 4 | 5 | def setup 6 | p = Axlsx::Package.new 7 | @ws = p.workbook.add_worksheet 8 | @ws.add_row ["one", 1, Time.now] 9 | chart = @ws.add_chart Axlsx::Bar3DChart 10 | @anchor = chart.graphic_frame.anchor 11 | end 12 | 13 | def test_initialization 14 | assert(@anchor.from.col == 0) 15 | assert(@anchor.from.row == 0) 16 | assert(@anchor.to.col == 5) 17 | assert(@anchor.to.row == 10) 18 | end 19 | 20 | def test_index 21 | assert_equal(@anchor.index, @anchor.drawing.anchors.index(@anchor)) 22 | end 23 | 24 | def test_options 25 | assert_raise(ArgumentError, 'invalid start_at') { @ws.add_chart Axlsx::Chart, :start_at=>"1" } 26 | assert_raise(ArgumentError, 'invalid end_at') { @ws.add_chart Axlsx::Chart, :start_at=>[1,2], :end_at => ["a", 4] } 27 | # this is actually raised in the graphic frame 28 | assert_raise(ArgumentError, 'invalid Chart') { @ws.add_chart Axlsx::TwoCellAnchor } 29 | a = @ws.add_chart Axlsx::Chart, :start_at => [15, 35], :end_at => [90, 45] 30 | assert_equal(a.graphic_frame.anchor.from.col, 15) 31 | assert_equal(a.graphic_frame.anchor.from.row, 35) 32 | assert_equal(a.graphic_frame.anchor.to.col, 90) 33 | assert_equal(a.graphic_frame.anchor.to.row, 45) 34 | end 35 | 36 | end 37 | -------------------------------------------------------------------------------- /test/drawing/tc_val_axis.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestValAxis < Test::Unit::TestCase 4 | def setup 5 | @axis = Axlsx::ValAxis.new 6 | end 7 | def teardown 8 | end 9 | 10 | def test_initialization 11 | assert_equal(@axis.cross_between, :between, "axis crossBetween default incorrect") 12 | end 13 | 14 | def test_options 15 | a = Axlsx::ValAxis.new(:cross_between => :midCat) 16 | assert_equal(:midCat, a.cross_between) 17 | end 18 | 19 | def test_crossBetween 20 | assert_raise(ArgumentError, "requires valid crossBetween") { @axis.cross_between = :my_eyes } 21 | assert_nothing_raised("accepts valid crossBetween") { @axis.cross_between = :midCat } 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /test/drawing/tc_view_3D.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestView3D < Test::Unit::TestCase 4 | def setup 5 | @view = Axlsx::View3D.new 6 | end 7 | 8 | def teardown 9 | end 10 | 11 | def test_options 12 | v = Axlsx::View3D.new :rot_x => 10, :rot_y => 5, :h_percent => "30%", :depth_percent => "45%", :r_ang_ax => false, :perspective => 10 13 | assert_equal(v.rot_x, 10) 14 | assert_equal(v.rot_y, 5) 15 | assert_equal(v.h_percent, "30%") 16 | assert_equal(v.depth_percent, "45%") 17 | assert_equal(v.r_ang_ax, false) 18 | assert_equal(v.perspective, 10) 19 | end 20 | 21 | def test_rot_x 22 | assert_raise(ArgumentError) {@view.rot_x = "bob"} 23 | assert_nothing_raised {@view.rot_x = -90} 24 | end 25 | 26 | def test_rot_y 27 | assert_raise(ArgumentError) {@view.rot_y = "bob"} 28 | assert_nothing_raised {@view.rot_y = 90} 29 | end 30 | 31 | def test_h_percent 32 | assert_raise(ArgumentError) {@view.h_percent = "bob"} 33 | assert_nothing_raised {@view.h_percent = "500%"} 34 | end 35 | 36 | def test_depth_percent 37 | assert_raise(ArgumentError) {@view.depth_percent = "bob"} 38 | assert_nothing_raised {@view.depth_percent = "20%"} 39 | end 40 | 41 | 42 | def test_rAngAx 43 | assert_raise(ArgumentError) {@view.rAngAx = "bob"} 44 | assert_nothing_raised {@view.rAngAx = true} 45 | end 46 | 47 | def test_perspective 48 | assert_raise(ArgumentError) {@view.perspective = "bob"} 49 | assert_nothing_raised {@view.perspective = 30} 50 | end 51 | 52 | 53 | 54 | end 55 | -------------------------------------------------------------------------------- /test/drawing/tc_vml_drawing.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestVmlDrawing < Test::Unit::TestCase 4 | 5 | def setup 6 | p = Axlsx::Package.new 7 | wb = p.workbook 8 | @ws = wb.add_worksheet 9 | @ws.add_comment :ref => 'A1', :text => 'penut machine', :author => 'crank' 10 | @ws.add_comment :ref => 'C3', :text => 'rust bucket', :author => 'PO' 11 | @vml_drawing = @ws.comments.vml_drawing 12 | end 13 | 14 | def test_initialize 15 | assert_raise(ArgumentError) { Axlsx::VmlDrawing.new } 16 | end 17 | 18 | def test_to_xml_string 19 | str = @vml_drawing.to_xml_string() 20 | doc = Nokogiri::XML(str) 21 | assert_equal(doc.xpath("//v:shape").size, 2) 22 | assert(doc.xpath("//o:idmap[@o:data='#{@ws.index+1}']")) 23 | end 24 | 25 | end 26 | -------------------------------------------------------------------------------- /test/profile.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -s 2 | 3 | $:.unshift "#{File.dirname(__FILE__)}/../lib" 4 | require 'axlsx' 5 | require 'ruby-prof' 6 | #RubyProf.measure_mode = RubyProf::MEMORY 7 | # 8 | row = [] 9 | # Taking worst case scenario of all string data 10 | input = (32..126).to_a.pack('U*').chars.to_a 11 | 20.times { row << input.shuffle.join} 12 | 13 | profile = RubyProf.profile do 14 | p = Axlsx::Package.new 15 | p.workbook.add_worksheet do |sheet| 16 | 10000.times do 17 | sheet << row 18 | end 19 | end 20 | p.to_stream 21 | end 22 | 23 | printer = RubyProf::FlatPrinter.new(profile) 24 | printer.print(STDOUT, {}) 25 | -------------------------------------------------------------------------------- /test/rels/tc_relationship.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestRelationships < Test::Unit::TestCase 4 | 5 | def test_instances_with_different_attributes_have_unique_ids 6 | rel_1 = Axlsx::Relationship.new(Object.new, Axlsx::WORKSHEET_R, 'target') 7 | rel_2 = Axlsx::Relationship.new(Object.new, Axlsx::COMMENT_R, 'foobar') 8 | assert_not_equal rel_1.Id, rel_2.Id 9 | end 10 | 11 | def test_instances_with_same_attributes_share_id 12 | source_obj = Object.new 13 | instance = Axlsx::Relationship.new(source_obj, Axlsx::WORKSHEET_R, 'target') 14 | assert_equal instance.Id, Axlsx::Relationship.new(source_obj, Axlsx::WORKSHEET_R, 'target').Id 15 | end 16 | 17 | def test_target_is_only_considered_for_same_attributes_check_if_target_mode_is_external 18 | source_obj = Object.new 19 | rel_1 = Axlsx::Relationship.new(source_obj, Axlsx::WORKSHEET_R, 'target') 20 | rel_2 = Axlsx::Relationship.new(source_obj, Axlsx::WORKSHEET_R, '../target') 21 | assert_equal rel_1.Id, rel_2.Id 22 | 23 | rel_3 = Axlsx::Relationship.new(source_obj, Axlsx::HYPERLINK_R, 'target', :target_mode => :External) 24 | rel_4 = Axlsx::Relationship.new(source_obj, Axlsx::HYPERLINK_R, '../target', :target_mode => :External) 25 | assert_not_equal rel_3.Id, rel_4.Id 26 | end 27 | 28 | def test_type 29 | assert_raise(ArgumentError) { Axlsx::Relationship.new nil, 'type', 'target' } 30 | assert_nothing_raised { Axlsx::Relationship.new nil, Axlsx::WORKSHEET_R, 'target' } 31 | assert_nothing_raised { Axlsx::Relationship.new nil, Axlsx::COMMENT_R, 'target' } 32 | end 33 | 34 | def test_target_mode 35 | assert_raise(ArgumentError) { Axlsx::Relationship.new nil, 'type', 'target', :target_mode => "FISH" } 36 | assert_nothing_raised { Axlsx::Relationship.new( nil, Axlsx::WORKSHEET_R, 'target', :target_mode => :External) } 37 | end 38 | 39 | def test_ampersand_escaping_in_target 40 | r = Axlsx::Relationship.new(nil, Axlsx::HYPERLINK_R, "http://example.com?foo=1&bar=2", :target_mod => :External) 41 | doc = Nokogiri::XML(r.to_xml_string) 42 | assert_equal(doc.xpath("//Relationship[@Target='http://example.com?foo=1&bar=2']").size, 1) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/rels/tc_relationships.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestRelationships < Test::Unit::TestCase 4 | 5 | def test_for 6 | source_obj_1, source_obj_2 = Object.new, Object.new 7 | rel_1 = Axlsx::Relationship.new(source_obj_1, Axlsx::WORKSHEET_R, "bar") 8 | rel_2 = Axlsx::Relationship.new(source_obj_2, Axlsx::WORKSHEET_R, "bar") 9 | rels = Axlsx::Relationships.new 10 | rels << rel_1 11 | rels << rel_2 12 | assert_equal rel_1, rels.for(source_obj_1) 13 | assert_equal rel_2, rels.for(source_obj_2) 14 | end 15 | 16 | def test_valid_document 17 | @rels = Axlsx::Relationships.new 18 | schema = Nokogiri::XML::Schema(File.open(Axlsx::RELS_XSD)) 19 | doc = Nokogiri::XML(@rels.to_xml_string) 20 | errors = [] 21 | schema.validate(doc).each do |error| 22 | puts error.message 23 | errors << error 24 | end 25 | 26 | @rels << Axlsx::Relationship.new(nil, Axlsx::WORKSHEET_R, "bar") 27 | doc = Nokogiri::XML(@rels.to_xml_string) 28 | errors = [] 29 | schema.validate(doc).each do |error| 30 | puts error.message 31 | errors << error 32 | end 33 | 34 | assert(errors.size == 0) 35 | end 36 | 37 | end 38 | -------------------------------------------------------------------------------- /test/stylesheet/tc_border.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestBorder < Test::Unit::TestCase 4 | def setup 5 | @b = Axlsx::Border.new 6 | end 7 | def teardown 8 | end 9 | def test_initialiation 10 | assert_equal(@b.diagonalUp, nil) 11 | assert_equal(@b.diagonalDown, nil) 12 | assert_equal(@b.outline, nil) 13 | assert(@b.prs.is_a?(Axlsx::SimpleTypedList)) 14 | end 15 | 16 | def test_diagonalUp 17 | assert_raise(ArgumentError) { @b.diagonalUp = :red } 18 | assert_nothing_raised { @b.diagonalUp = true } 19 | assert_equal(@b.diagonalUp, true ) 20 | end 21 | 22 | def test_diagonalDown 23 | assert_raise(ArgumentError) { @b.diagonalDown = :red } 24 | assert_nothing_raised { @b.diagonalDown = true } 25 | assert_equal(@b.diagonalDown, true ) 26 | end 27 | 28 | def test_outline 29 | assert_raise(ArgumentError) { @b.outline = :red } 30 | assert_nothing_raised { @b.outline = true } 31 | assert_equal(@b.outline, true ) 32 | end 33 | 34 | def test_prs 35 | assert_nothing_raised { @b.prs << Axlsx::BorderPr.new(:name=>:top, :style=>:thin, :color => Axlsx::Color.new(:rgb=>"FF0000FF")) } 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/stylesheet/tc_border_pr.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestBorderPr < Test::Unit::TestCase 4 | def setup 5 | @bpr = Axlsx::BorderPr.new 6 | end 7 | def teardown 8 | end 9 | def test_initialiation 10 | assert_equal(@bpr.color, nil) 11 | assert_equal(@bpr.style, nil) 12 | assert_equal(@bpr.name, nil) 13 | end 14 | 15 | def test_color 16 | assert_raise(ArgumentError) { @bpr.color = :red } 17 | assert_nothing_raised { @bpr.color = Axlsx::Color.new :rgb=>"FF000000" } 18 | assert(@bpr.color.is_a?(Axlsx::Color)) 19 | end 20 | 21 | def test_style 22 | assert_raise(ArgumentError) { @bpr.style = :red } 23 | assert_nothing_raised { @bpr.style = :thin } 24 | assert_equal(@bpr.style, :thin) 25 | end 26 | 27 | def test_name 28 | assert_raise(ArgumentError) { @bpr.name = :red } 29 | assert_nothing_raised { @bpr.name = :top } 30 | assert_equal(@bpr.name, :top) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /test/stylesheet/tc_cell_protection.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestCellProtection < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::CellProtection.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | def test_initialiation 13 | assert_equal(@item.hidden, nil) 14 | assert_equal(@item.locked, nil) 15 | end 16 | 17 | def test_hidden 18 | assert_raise(ArgumentError) { @item.hidden = -1 } 19 | assert_nothing_raised { @item.hidden = false } 20 | assert_equal(@item.hidden, false ) 21 | end 22 | 23 | def test_locked 24 | assert_raise(ArgumentError) { @item.locked = -1 } 25 | assert_nothing_raised { @item.locked = false } 26 | assert_equal(@item.locked, false ) 27 | end 28 | 29 | end 30 | -------------------------------------------------------------------------------- /test/stylesheet/tc_cell_style.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestCellStyle < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::CellStyle.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | def test_initialiation 13 | assert_equal(@item.name, nil) 14 | assert_equal(@item.xfId, nil) 15 | assert_equal(@item.builtinId, nil) 16 | assert_equal(@item.iLevel, nil) 17 | assert_equal(@item.hidden, nil) 18 | assert_equal(@item.customBuiltin, nil) 19 | end 20 | 21 | def test_name 22 | assert_raise(ArgumentError) { @item.name = -1 } 23 | assert_nothing_raised { @item.name = "stylin" } 24 | assert_equal(@item.name, "stylin" ) 25 | end 26 | 27 | def test_xfId 28 | assert_raise(ArgumentError) { @item.xfId = -1 } 29 | assert_nothing_raised { @item.xfId = 5 } 30 | assert_equal(@item.xfId, 5 ) 31 | end 32 | 33 | def test_builtinId 34 | assert_raise(ArgumentError) { @item.builtinId = -1 } 35 | assert_nothing_raised { @item.builtinId = 5 } 36 | assert_equal(@item.builtinId, 5 ) 37 | end 38 | 39 | def test_iLevel 40 | assert_raise(ArgumentError) { @item.iLevel = -1 } 41 | assert_nothing_raised { @item.iLevel = 5 } 42 | assert_equal(@item.iLevel, 5 ) 43 | end 44 | 45 | def test_hidden 46 | assert_raise(ArgumentError) { @item.hidden = -1 } 47 | assert_nothing_raised { @item.hidden = true } 48 | assert_equal(@item.hidden, true ) 49 | end 50 | 51 | def test_customBuiltin 52 | assert_raise(ArgumentError) { @item.customBuiltin = -1 } 53 | assert_nothing_raised { @item.customBuiltin = true } 54 | assert_equal(@item.customBuiltin, true ) 55 | end 56 | 57 | end 58 | -------------------------------------------------------------------------------- /test/stylesheet/tc_color.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestColor < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::Color.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | def test_initialiation 13 | assert_equal(@item.auto, nil) 14 | assert_equal(@item.rgb, "FF000000") 15 | assert_equal(@item.tint, nil) 16 | end 17 | 18 | def test_auto 19 | assert_raise(ArgumentError) { @item.auto = -1 } 20 | assert_nothing_raised { @item.auto = true } 21 | assert_equal(@item.auto, true ) 22 | end 23 | 24 | def test_rgb 25 | assert_raise(ArgumentError) { @item.rgb = -1 } 26 | assert_nothing_raised { @item.rgb = "FF00FF00" } 27 | assert_equal(@item.rgb, "FF00FF00" ) 28 | end 29 | 30 | def test_rgb_writer_doesnt_mutate_its_argument 31 | my_rgb = 'ff00ff00' 32 | @item.rgb = my_rgb 33 | assert_equal 'ff00ff00', my_rgb 34 | end 35 | 36 | def test_tint 37 | assert_raise(ArgumentError) { @item.tint = -1 } 38 | assert_nothing_raised { @item.tint = -1.0 } 39 | assert_equal(@item.tint, -1.0 ) 40 | end 41 | 42 | 43 | end 44 | -------------------------------------------------------------------------------- /test/stylesheet/tc_fill.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestFill < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::Fill.new Axlsx::PatternFill.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | def test_initialiation 13 | assert(@item.fill_type.is_a?(Axlsx::PatternFill)) 14 | assert_raise(ArgumentError) { Axlsx::Fill.new } 15 | assert_nothing_raised { Axlsx::Fill.new(Axlsx::GradientFill.new) } 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /test/stylesheet/tc_gradient_fill.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestGradientFill < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::GradientFill.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | 13 | def test_initialiation 14 | assert_equal(@item.type, :linear) 15 | assert_equal(@item.degree, nil) 16 | assert_equal(@item.left, nil) 17 | assert_equal(@item.right, nil) 18 | assert_equal(@item.top, nil) 19 | assert_equal(@item.bottom, nil) 20 | assert(@item.stop.is_a?(Axlsx::SimpleTypedList)) 21 | end 22 | 23 | def test_type 24 | assert_raise(ArgumentError) { @item.type = 7 } 25 | assert_nothing_raised { @item.type = :path } 26 | assert_equal(@item.type, :path) 27 | end 28 | 29 | def test_degree 30 | assert_raise(ArgumentError) { @item.degree = -7 } 31 | assert_nothing_raised { @item.degree = 5.0 } 32 | assert_equal(@item.degree, 5.0) 33 | end 34 | 35 | def test_left 36 | assert_raise(ArgumentError) { @item.left = -1.1 } 37 | assert_nothing_raised { @item.left = 1.0 } 38 | assert_equal(@item.left, 1.0) 39 | end 40 | 41 | def test_right 42 | assert_raise(ArgumentError) { @item.right = -1.1 } 43 | assert_nothing_raised { @item.right = 0.5 } 44 | assert_equal(@item.right, 0.5) 45 | end 46 | 47 | def test_top 48 | assert_raise(ArgumentError) { @item.top = -1.1 } 49 | assert_nothing_raised { @item.top = 1.0 } 50 | assert_equal(@item.top, 1.0) 51 | end 52 | 53 | def test_bottom 54 | assert_raise(ArgumentError) { @item.bottom = -1.1 } 55 | assert_nothing_raised { @item.bottom = 0.0 } 56 | assert_equal(@item.bottom, 0.0) 57 | end 58 | 59 | def test_stop 60 | @item.stop << Axlsx::GradientStop.new(Axlsx::Color.new(:rgb=>"00000000"), 0.5) 61 | assert(@item.stop.size == 1) 62 | assert(@item.stop.last.is_a?(Axlsx::GradientStop)) 63 | end 64 | 65 | def test_to_xml_string 66 | @item.stop << Axlsx::GradientStop.new(Axlsx::Color.new(:rgb => "000000"), 0.5) 67 | @item.stop << Axlsx::GradientStop.new(Axlsx::Color.new(:rgb => "FFFFFF"), 0.5) 68 | @item.type = :path 69 | doc = Nokogiri::XML(@item.to_xml_string) 70 | assert(doc.xpath("//color[@rgb='FF000000']")) 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /test/stylesheet/tc_gradient_stop.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestGradientStop < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::GradientStop.new(Axlsx::Color.new(:rgb=>"FFFF0000"), 1.0) 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | 13 | def test_initialiation 14 | assert_equal(@item.color.rgb, "FFFF0000") 15 | assert_equal(@item.position, 1.0) 16 | end 17 | 18 | def test_position 19 | assert_raise(ArgumentError) { @item.position = -1.1 } 20 | assert_nothing_raised { @item.position = 0.0 } 21 | assert_equal(@item.position, 0.0) 22 | end 23 | 24 | def test_color 25 | assert_raise(ArgumentError) { @item.color = nil } 26 | color = Axlsx::Color.new(:rgb=>"FF0000FF") 27 | @item.color = color 28 | assert_equal(@item.color.rgb, "FF0000FF") 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /test/stylesheet/tc_num_fmt.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestNumFmt < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::NumFmt.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | 13 | def test_initialiation 14 | assert_equal(@item.numFmtId, 0) 15 | assert_equal(@item.formatCode, "") 16 | end 17 | 18 | def test_numFmtId 19 | assert_raise(ArgumentError) { @item.numFmtId = -1.1 } 20 | assert_nothing_raised { @item.numFmtId = 2 } 21 | assert_equal(@item.numFmtId, 2) 22 | end 23 | 24 | def test_fomatCode 25 | assert_raise(ArgumentError) { @item.formatCode = -1.1 } 26 | assert_nothing_raised { @item.formatCode = "0" } 27 | assert_equal(@item.formatCode, "0") 28 | end 29 | 30 | end 31 | -------------------------------------------------------------------------------- /test/stylesheet/tc_pattern_fill.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestPatternFill < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::PatternFill.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | 13 | def test_initialiation 14 | assert_equal(@item.patternType, :none) 15 | assert_equal(@item.bgColor, nil) 16 | assert_equal(@item.fgColor, nil) 17 | end 18 | 19 | def test_bgColor 20 | assert_raise(ArgumentError) { @item.bgColor = -1.1 } 21 | assert_nothing_raised { @item.bgColor = Axlsx::Color.new } 22 | assert_equal(@item.bgColor.rgb, "FF000000") 23 | end 24 | 25 | def test_fgColor 26 | assert_raise(ArgumentError) { @item.fgColor = -1.1 } 27 | assert_nothing_raised { @item.fgColor = Axlsx::Color.new } 28 | assert_equal(@item.fgColor.rgb, "FF000000") 29 | end 30 | 31 | def test_pattern_type 32 | assert_raise(ArgumentError) { @item.patternType = -1.1 } 33 | assert_nothing_raised { @item.patternType = :lightUp } 34 | assert_equal(@item.patternType, :lightUp) 35 | end 36 | 37 | def test_to_xml_string 38 | @item = Axlsx::PatternFill.new :bgColor => Axlsx::Color.new(:rgb => "FF0000"), :fgColor => Axlsx::Color.new(:rgb=>"00FF00") 39 | doc = Nokogiri::XML(@item.to_xml_string) 40 | assert(doc.xpath('//color[@rgb="FFFF0000"]')) 41 | assert(doc.xpath('//color[@rgb="FF00FF00"]')) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/stylesheet/tc_table_style.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestTableStyle < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::TableStyle.new "fisher" 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | def test_initialiation 13 | assert_equal(@item.name, "fisher") 14 | assert_equal(@item.pivot, nil) 15 | assert_equal(@item.table, nil) 16 | ts = Axlsx::TableStyle.new 'price', :pivot => true, :table => true 17 | assert_equal(ts.name, 'price') 18 | assert_equal(ts.pivot, true) 19 | assert_equal(ts.table, true) 20 | end 21 | 22 | def test_name 23 | assert_raise(ArgumentError) { @item.name = -1.1 } 24 | assert_nothing_raised { @item.name = "lovely table style" } 25 | assert_equal(@item.name, "lovely table style") 26 | end 27 | 28 | def test_pivot 29 | assert_raise(ArgumentError) { @item.pivot = -1.1 } 30 | assert_nothing_raised { @item.pivot = true } 31 | assert_equal(@item.pivot, true) 32 | end 33 | 34 | def test_table 35 | assert_raise(ArgumentError) { @item.table = -1.1 } 36 | assert_nothing_raised { @item.table = true } 37 | assert_equal(@item.table, true) 38 | end 39 | 40 | def test_to_xml_string 41 | doc = Nokogiri::XML(@item.to_xml_string) 42 | assert(doc.xpath("//tableStyle[@name='#{@item.name}']")) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/stylesheet/tc_table_style_element.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestTableStyleElement < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::TableStyleElement.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | def test_initialiation 13 | assert_equal(@item.type, nil) 14 | assert_equal(@item.size, nil) 15 | assert_equal(@item.dxfId, nil) 16 | options = { :type => :headerRow, :size => 10, :dxfId => 1 } 17 | 18 | tse = Axlsx::TableStyleElement.new options 19 | options.each { |key, value| assert_equal(tse.send(key.to_sym), value) } 20 | end 21 | 22 | def test_type 23 | assert_raise(ArgumentError) { @item.type = -1.1 } 24 | assert_nothing_raised { @item.type = :blankRow } 25 | assert_equal(@item.type, :blankRow) 26 | end 27 | 28 | def test_size 29 | assert_raise(ArgumentError) { @item.size = -1.1 } 30 | assert_nothing_raised { @item.size = 2 } 31 | assert_equal(@item.size, 2) 32 | end 33 | 34 | def test_dxfId 35 | assert_raise(ArgumentError) { @item.dxfId = -1.1 } 36 | assert_nothing_raised { @item.dxfId = 7 } 37 | assert_equal(@item.dxfId, 7) 38 | end 39 | 40 | def test_to_xml_string 41 | doc = Nokogiri::XML(@item.to_xml_string) 42 | @item.type = :headerRow 43 | assert(doc.xpath("//tableStyleElement[@type='#{@item.type.to_s}']")) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /test/stylesheet/tc_table_styles.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestTableStyles < Test::Unit::TestCase 4 | 5 | def setup 6 | @item = Axlsx::TableStyles.new 7 | end 8 | 9 | def teardown 10 | end 11 | 12 | def test_initialiation 13 | assert_equal(@item.defaultTableStyle, "TableStyleMedium9") 14 | assert_equal(@item.defaultPivotStyle, "PivotStyleLight16") 15 | end 16 | 17 | def test_defaultTableStyle 18 | assert_raise(ArgumentError) { @item.defaultTableStyle = -1.1 } 19 | assert_nothing_raised { @item.defaultTableStyle = "anyones guess" } 20 | assert_equal(@item.defaultTableStyle, "anyones guess") 21 | end 22 | 23 | def test_defaultPivotStyle 24 | assert_raise(ArgumentError) { @item.defaultPivotStyle = -1.1 } 25 | assert_nothing_raised { @item.defaultPivotStyle = "anyones guess" } 26 | assert_equal(@item.defaultPivotStyle, "anyones guess") 27 | end 28 | 29 | end 30 | -------------------------------------------------------------------------------- /test/tc_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" 2 | require 'simplecov' 3 | SimpleCov.start do 4 | add_filter "/test/" 5 | add_filter "/vendor/" 6 | end 7 | 8 | require 'test/unit' 9 | require "timecop" 10 | require "axlsx.rb" 11 | # MIME detection for Microsoft Office 2007+ formats 12 | require 'mimemagic/overlay' 13 | -------------------------------------------------------------------------------- /test/util/tc_mime_type_utils.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | class TestMimeTypeUtils < Test::Unit::TestCase 3 | def setup 4 | @test_img = File.dirname(__FILE__) + "/../../examples/image1.jpeg" 5 | end 6 | 7 | def teardown 8 | end 9 | 10 | def test_mime_type_utils 11 | assert_equal(Axlsx::MimeTypeUtils::get_mime_type(@test_img), 'image/jpeg') 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/util/tc_serialized_attributes.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | class Funk 3 | include Axlsx::Accessors 4 | include Axlsx::SerializedAttributes 5 | serializable_attributes :camel_symbol, :boolean, :integer 6 | 7 | attr_accessor :camel_symbol, :boolean, :integer 8 | end 9 | 10 | class TestSeralizedAttributes < Test::Unit::TestCase 11 | def setup 12 | @object = Funk.new 13 | end 14 | 15 | def test_camel_symbol 16 | @object.camel_symbol = :foo_bar 17 | assert_equal('camelSymbol="fooBar" ', @object.serialized_attributes) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/workbook/tc_defined_name.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper' 2 | 3 | class TestDefinedNames < Test::Unit::TestCase 4 | def setup 5 | @dn = Axlsx::DefinedName.new('Sheet1!A1:A1') 6 | end 7 | 8 | def test_initialize 9 | assert_equal('Sheet1!A1:A1', @dn.formula) 10 | end 11 | 12 | def test_string_attributes 13 | %w(short_cut_key status_bar help description custom_menu comment).each do |attr| 14 | assert_raise(ArgumentError, 'only strings allowed in string attributes') { @dn.send("#{attr}=", 1) } 15 | assert_nothing_raised { @dn.send("#{attr}=", '_xlnm.Sheet_Title') } 16 | end 17 | end 18 | 19 | def test_boolean_attributes 20 | %w(workbook_parameter publish_to_server xlm vb_proceedure function hidden).each do |attr| 21 | assert_raise(ArgumentError, 'only booleanish allowed in string attributes') { @dn.send("#{attr}=", 'foo') } 22 | assert_nothing_raised { @dn.send("#{attr}=", 1) } 23 | end 24 | 25 | end 26 | 27 | def test_local_sheet_id 28 | assert_raise(ArgumentError, 'local_sheet_id must be an unsigned int') { @dn.local_sheet_id = -1 } 29 | assert_nothing_raised { @dn.local_sheet_id = 1 } 30 | end 31 | 32 | def test_do_not_camelcase_value_for_name 33 | @dn.name = '_xlnm._FilterDatabase' 34 | doc = Nokogiri::XML(@dn.to_xml_string) 35 | assert_equal(doc.xpath("//definedName[@name='_xlnm._FilterDatabase']").size, 1) 36 | assert_equal('Sheet1!A1:A1', doc.xpath('//definedName').text) 37 | end 38 | 39 | def test_to_xml_string 40 | assert_raise(ArgumentError, 'name is required for serialization') { @dn.to_xml_string } 41 | @dn.name = '_xlnm.Print_Titles' 42 | @dn.hidden = true 43 | doc = Nokogiri::XML(@dn.to_xml_string) 44 | assert_equal(doc.xpath("//definedName[@name='_xlnm.Print_Titles']").size, 1) 45 | assert_equal(doc.xpath("//definedName[@hidden='1']").size, 1) 46 | assert_equal('Sheet1!A1:A1', doc.xpath('//definedName').text) 47 | end 48 | 49 | end 50 | -------------------------------------------------------------------------------- /test/workbook/tc_shared_strings_table.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestSharedStringsTable < Test::Unit::TestCase 4 | 5 | def setup 6 | @p = Axlsx::Package.new :use_shared_strings=>true 7 | 8 | ws = @p.workbook.add_worksheet 9 | ws.add_row ['a', 1, 'b'] 10 | ws.add_row ['b', 1, 'c'] 11 | ws.add_row ['c', 1, 'd'] 12 | ws.rows.last.add_cell('b', :type => :text) 13 | end 14 | 15 | def test_workbook_has_shared_strings 16 | assert(@p.workbook.shared_strings.is_a?(Axlsx::SharedStringsTable), "shared string table was not created") 17 | end 18 | 19 | def test_count 20 | sst = @p.workbook.shared_strings 21 | assert_equal(sst.count, 7) 22 | end 23 | 24 | def test_unique_count 25 | sst = @p.workbook.shared_strings 26 | assert_equal(sst.unique_count, 4) 27 | end 28 | 29 | def test_uses_workbook_xml_space 30 | assert_equal(@p.workbook.xml_space, @p.workbook.shared_strings.xml_space) 31 | @p.workbook.xml_space = :default 32 | assert_equal(:default, @p.workbook.shared_strings.xml_space) 33 | end 34 | 35 | def test_valid_document 36 | schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) 37 | doc = Nokogiri::XML(@p.workbook.shared_strings.to_xml_string) 38 | errors = [] 39 | schema.validate(doc).each do |error| 40 | puts error.message 41 | errors << error 42 | end 43 | assert_equal(errors.size, 0, "sharedStirngs.xml Invalid" + errors.map{ |e| e.message }.to_s) 44 | end 45 | 46 | def test_remove_control_characters_in_xml_serialization 47 | nasties = "hello\x10\x00\x1C\x1Eworld" 48 | @p.workbook.worksheets[0].add_row [nasties] 49 | 50 | # test that the nasty string was added to the shared strings 51 | assert @p.workbook.shared_strings.unique_cells.has_key?(nasties) 52 | 53 | # test that none of the control characters are in the XML output for shared strings 54 | assert_no_match(/#{Axlsx::CONTROL_CHARS}/, @p.workbook.shared_strings.to_xml_string) 55 | 56 | # assert that the shared string was normalized to remove the control characters 57 | assert_not_nil @p.workbook.shared_strings.to_xml_string.index("helloworld") 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /test/workbook/tc_workbook_view.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper' 2 | 3 | class TestWorkbookView < Test::Unit::TestCase 4 | 5 | def setup 6 | @options = { visibility: :hidden, minimized: true, show_horizontal_scroll: true, show_vertical_scroll: true, 7 | show_sheet_tabs: true, tab_ratio: 750, first_sheet: 0, active_tab: 1, x_window: 500, y_window: 400, 8 | window_width: 800, window_height: 600, auto_filter_date_grouping: true } 9 | @book_view = Axlsx::WorkbookView.new @options 10 | end 11 | 12 | def test_options_assignation 13 | @options.each do |key, value| 14 | assert_equal(value, @book_view.send(key)) 15 | end 16 | end 17 | 18 | def test_boolean_attribute_validation 19 | %w(minimized show_horizontal_scroll show_vertical_scroll show_sheet_tabs auto_filter_date_grouping).each do |attr| 20 | assert_raise(ArgumentError, 'only booleanish allowed in boolean attributes') { @book_view.send("#{attr}=", "banana") } 21 | assert_nothing_raised { @book_view.send("#{attr}=", false )} 22 | end 23 | end 24 | 25 | def test_integer_attribute_validation 26 | %w(tab_ratio first_sheet active_tab x_window y_window window_width window_height).each do |attr| 27 | assert_raise(ArgumentError, 'only integer allowed in integer attributes') { @book_view.send("#{attr}=", "b") } 28 | assert_nothing_raised { @book_view.send("#{attr}=", 7 )} 29 | end 30 | end 31 | 32 | def test_visibility_attribute_validation 33 | assert_raise(ArgumentError) { @book_view.visibility = :foobar } 34 | assert_nothing_raised { @book_view.visibility = :hidden } 35 | assert_nothing_raised { @book_view.visibility = :very_hidden } 36 | assert_nothing_raised { @book_view.visibility = :visible } 37 | end 38 | 39 | def test_to_xml_string 40 | xml = @book_view.to_xml_string 41 | doc = Nokogiri::XML(xml) 42 | @options.each do |key, value| 43 | if value == true || value == false 44 | value = value ? 1 : 0 45 | end 46 | path = "workbookView[@#{Axlsx.camel(key, false)}='#{value}']" 47 | assert_equal(1, doc.xpath(path).size) 48 | end 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /test/workbook/worksheet/auto_filter/tc_auto_filter.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestAutoFilter < Test::Unit::TestCase 4 | 5 | def setup 6 | ws = Axlsx::Package.new.workbook.add_worksheet 7 | 3.times { |index| ws.add_row [1*index,2*index,3*index] } 8 | @auto_filter = ws.auto_filter 9 | @auto_filter.range = 'A1:C3' 10 | @auto_filter.add_column 0, :filters, :filter_items => [1] 11 | end 12 | 13 | def test_defined_name 14 | assert_equal("'Sheet1'!$A$1:$C$3", @auto_filter.defined_name) 15 | end 16 | 17 | def test_to_xml_string 18 | doc = Nokogiri::XML(@auto_filter.to_xml_string) 19 | assert(doc.xpath("autoFilter[@ref='#{@auto_filter.range}']")) 20 | end 21 | 22 | def test_columns 23 | assert @auto_filter.columns.is_a?(Axlsx::SimpleTypedList) 24 | assert_equal @auto_filter.columns.allowed_types, [Axlsx::FilterColumn] 25 | end 26 | 27 | def test_add_column 28 | @auto_filter.add_column(0, :filters) do |column| 29 | assert column.is_a? FilterColumn 30 | end 31 | end 32 | 33 | def test_applya 34 | assert_equal nil, @auto_filter.worksheet.rows.last.hidden 35 | @auto_filter.apply 36 | assert_equal true, @auto_filter.worksheet.rows.last.hidden 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /test/workbook/worksheet/auto_filter/tc_filters.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestFilters < Test::Unit::TestCase 4 | def setup 5 | @filters = Axlsx::Filters.new(:filter_items => [1, 'a'], 6 | :date_group_items =>[ { :date_time_grouping => :year, :year => 2011, :month => 11, :day => 11, :hour => 0, :minute => 0, :second => 0 } ] , 7 | :blank => true) 8 | end 9 | 10 | def test_blank 11 | assert_equal true, @filters.blank 12 | assert_raise(ArgumentError) { @filters.blank = :only_if_you_want_it } 13 | @filters.blank = true 14 | assert_equal true, @filters.blank 15 | end 16 | 17 | def test_calendar_type 18 | assert_raise(ArgumentError) { @filters.calendar_type = 'monkey calendar' } 19 | @filters.calendar_type = 'japan' 20 | assert_equal('japan', @filters.calendar_type) 21 | end 22 | 23 | def test_filters_items 24 | assert @filters.filter_items.is_a?(Array) 25 | assert_equal 2, @filters.filter_items.size 26 | end 27 | 28 | def test_date_group_items 29 | assert @filters.date_group_items.is_a?(Array) 30 | assert_equal 1, @filters.date_group_items.size 31 | end 32 | 33 | def test_apply_is_false_for_matching_values 34 | keeper = Object.new 35 | def keeper.value; 'a'; end 36 | assert_equal false, @filters.apply(keeper) 37 | end 38 | 39 | def test_apply_is_true_for_non_matching_values 40 | hidden = Object.new 41 | def hidden.value; 'b'; end 42 | assert_equal true, @filters.apply(hidden) 43 | end 44 | 45 | def test_to_xml_string 46 | doc = Nokogiri::XML(@filters.to_xml_string) 47 | assert_equal(1, doc.xpath('//filters[@blank=1]').size) 48 | end 49 | end 50 | 51 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_break.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestBreak < Test::Unit::TestCase 4 | 5 | def setup 6 | @break = Axlsx::Break.new(:id => 1, :min => 1, :max => 10, :man => true, :pt => false) 7 | end 8 | 9 | def test_id 10 | assert_equal(1, @break.id) 11 | assert_raises ArgumentError do 12 | Axlsx::Break.new(:hoge, {:id => -1}) 13 | end 14 | end 15 | 16 | def test_min 17 | assert_equal(1, @break.min) 18 | assert_raises ArgumentError do 19 | Axlsx::Break.new(:hoge, :min => -1) 20 | end 21 | end 22 | 23 | def test_max 24 | assert_equal(10, @break.max) 25 | assert_raises ArgumentError do 26 | Axlsx::Break.new(:hoge, :max => -1) 27 | end 28 | end 29 | 30 | 31 | def test_man 32 | assert_equal(true, @break.man) 33 | assert_raises ArgumentError do 34 | Axlsx::Break.new(:man => -1) 35 | end 36 | end 37 | 38 | def test_pt 39 | assert_equal(false, @break.pt) 40 | assert_raises ArgumentError do 41 | Axlsx::Break.new(:pt => -1) 42 | end 43 | end 44 | 45 | def test_to_xml_string 46 | doc = Nokogiri::XML(@break.to_xml_string) 47 | assert_equal(doc.xpath('//brk[@id="1"][@min="1"][@max="10"][@pt=0][@man=1]').size, 1) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_cfvo.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestCfvo < Test::Unit::TestCase 4 | def setup 5 | @cfvo = Axlsx::Cfvo.new(:val => "0", :type => :min) 6 | end 7 | 8 | def test_val 9 | assert_nothing_raised { @cfvo.val = "abc" } 10 | assert_equal(@cfvo.val, "abc") 11 | end 12 | 13 | def test_type 14 | assert_raise(ArgumentError) { @cfvo.type = :invalid_type } 15 | assert_nothing_raised { @cfvo.type = :max } 16 | assert_equal(@cfvo.type, :max) 17 | end 18 | 19 | def test_gte 20 | assert_raise(ArgumentError) { @cfvo.gte = :bob } 21 | assert_equal(@cfvo.gte, true) 22 | assert_nothing_raised { @cfvo.gte = false } 23 | assert_equal(@cfvo.gte, false) 24 | end 25 | 26 | def test_to_xml_string 27 | doc = Nokogiri::XML.parse(@cfvo.to_xml_string) 28 | assert doc.xpath(".//cfvo[@type='min'][@val=0][@gte=true]") 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_color_scale.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestColorScale < Test::Unit::TestCase 4 | def setup 5 | @color_scale = Axlsx::ColorScale.new 6 | end 7 | 8 | def test_three_tone 9 | color_scale = Axlsx::ColorScale.three_tone 10 | assert_equal 3, color_scale.value_objects.size 11 | assert_equal 3, color_scale.colors.size 12 | end 13 | 14 | def test_two_tone 15 | color_scale = Axlsx::ColorScale.two_tone 16 | assert_equal 2, color_scale.value_objects.size 17 | assert_equal 2, color_scale.colors.size 18 | end 19 | def test_default_cfvo 20 | first = Axlsx::ColorScale.default_cfvos.first 21 | second = Axlsx::ColorScale.default_cfvos.last 22 | assert_equal 'FFFF7128', first[:color] 23 | assert_equal :min,first[:type] 24 | assert_equal 0, first[:val] 25 | 26 | assert_equal 'FFFFEF9C', second[:color] 27 | assert_equal :max, second[:type] 28 | assert_equal 0, second[:val] 29 | end 30 | 31 | def test_partial_default_cfvo_override 32 | first_def = {:type => :percent, :val => "10.0", :color => 'FF00FF00'} 33 | color_scale = Axlsx::ColorScale.new(first_def) 34 | assert_equal color_scale.value_objects.first.val, first_def[:val] 35 | assert_equal color_scale.value_objects.first.type, first_def[:type] 36 | assert_equal color_scale.colors.first.rgb, first_def[:color] 37 | end 38 | 39 | def test_add 40 | @color_scale.add :type => :max, :val => 5, :color => "FFDEDEDE" 41 | assert_equal(@color_scale.value_objects.size,3) 42 | assert_equal(@color_scale.colors.size,3) 43 | end 44 | 45 | def test_delete_at 46 | @color_scale.add :type => :max, :val => 5, :color => "FFDEDEDE" 47 | assert_nothing_raised {@color_scale.delete_at 2} 48 | assert_equal(@color_scale.value_objects.size,2) 49 | assert_equal(@color_scale.colors.size,2) 50 | end 51 | 52 | def test_to_xml_string 53 | doc = Nokogiri::XML.parse(@color_scale.to_xml_string) 54 | assert_equal(doc.xpath(".//colorScale//cfvo").size, 2) 55 | assert_equal(doc.xpath(".//colorScale//color").size, 2) 56 | end 57 | 58 | end 59 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_data_bar.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestDataBar < Test::Unit::TestCase 4 | def setup 5 | @data_bar = Axlsx::DataBar.new :color => "FF638EC6" 6 | end 7 | 8 | def test_defaults 9 | assert_equal @data_bar.minLength, 10 10 | assert_equal @data_bar.maxLength, 90 11 | assert_equal @data_bar.showValue, true 12 | end 13 | 14 | def test_override_default_cfvos 15 | data_bar = Axlsx::DataBar.new({:color => 'FF00FF00'}, {:type => :min, :val => "20"}) 16 | assert_equal("20", data_bar.value_objects.first.val) 17 | assert_equal("0", data_bar.value_objects.last.val) 18 | end 19 | 20 | 21 | def test_minLength 22 | assert_raise(ArgumentError) { @data_bar.minLength = :invalid_type } 23 | assert_nothing_raised { @data_bar.minLength = 0} 24 | assert_equal(@data_bar.minLength, 0) 25 | end 26 | 27 | def test_maxLength 28 | assert_raise(ArgumentError) { @data_bar.maxLength = :invalid_type } 29 | assert_nothing_raised { @data_bar.maxLength = 0} 30 | assert_equal(@data_bar.maxLength, 0) 31 | end 32 | 33 | def test_showValue 34 | assert_raise(ArgumentError) { @data_bar.showValue = :invalid_type } 35 | assert_nothing_raised { @data_bar.showValue = false} 36 | assert_equal(@data_bar.showValue, false) 37 | end 38 | 39 | def test_to_xml_string 40 | doc = Nokogiri::XML.parse(@data_bar.to_xml_string) 41 | assert_equal(doc.xpath(".//dataBar[@minLength=10][@maxLength=90][@showValue=1]").size, 1) 42 | assert_equal(doc.xpath(".//dataBar//cfvo").size, 2) 43 | assert_equal(doc.xpath(".//dataBar//color").size, 1) 44 | end 45 | 46 | end 47 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_icon_set.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestIconSet < Test::Unit::TestCase 4 | def setup 5 | @icon_set = Axlsx::IconSet.new 6 | end 7 | 8 | def test_defaults 9 | assert_equal @icon_set.iconSet, "3TrafficLights1" 10 | assert_equal @icon_set.percent, true 11 | assert_equal @icon_set.reverse, false 12 | assert_equal @icon_set.showValue, true 13 | end 14 | 15 | def test_icon_set 16 | assert_raise(ArgumentError) { @icon_set.iconSet = "invalid_value" } 17 | assert_nothing_raised { @icon_set.iconSet = "5Rating"} 18 | assert_equal(@icon_set.iconSet, "5Rating") 19 | end 20 | 21 | def test_percent 22 | assert_raise(ArgumentError) { @icon_set.percent = :invalid_type } 23 | assert_nothing_raised { @icon_set.percent = false} 24 | assert_equal(@icon_set.percent, false) 25 | end 26 | 27 | def test_showValue 28 | assert_raise(ArgumentError) { @icon_set.showValue = :invalid_type } 29 | assert_nothing_raised { @icon_set.showValue = false} 30 | assert_equal(@icon_set.showValue, false) 31 | end 32 | 33 | def test_reverse 34 | assert_raise(ArgumentError) { @icon_set.reverse = :invalid_type } 35 | assert_nothing_raised { @icon_set.reverse = false} 36 | assert_equal(@icon_set.reverse, false) 37 | end 38 | 39 | def test_to_xml_string 40 | doc = Nokogiri::XML.parse(@icon_set.to_xml_string) 41 | assert_equal(doc.xpath(".//iconSet[@iconSet='3TrafficLights1'][@percent=1][@reverse=0][@showValue=1]").size, 1) 42 | assert_equal(doc.xpath(".//iconSet//cfvo").size, 3) 43 | end 44 | 45 | end 46 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_outline_pr.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestOutlinePr < Test::Unit::TestCase 4 | def setup 5 | @outline_pr = Axlsx::OutlinePr.new(:summary_below => false, :summary_right => true, :apply_styles => false) 6 | end 7 | 8 | def test_summary_below 9 | assert_equal false, @outline_pr.summary_below 10 | end 11 | 12 | def test_summary_right 13 | assert_equal true, @outline_pr.summary_right 14 | end 15 | 16 | def test_apply_styles 17 | assert_equal false, @outline_pr.apply_styles 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_page_set_up_pr.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestPageSetUpPr < Test::Unit::TestCase 4 | def setup 5 | @page_setup_pr = Axlsx::PageSetUpPr.new(:fit_to_page => true, :auto_page_breaks => true) 6 | end 7 | 8 | def test_fit_to_page 9 | assert_equal true, @page_setup_pr.fit_to_page 10 | end 11 | 12 | def test_auto_page_breaks 13 | assert_equal true, @page_setup_pr.auto_page_breaks 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_pane.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../" 3 | require 'tc_helper.rb' 4 | 5 | class TestPane < Test::Unit::TestCase 6 | def setup 7 | #inverse defaults for booleans 8 | @nil_options = { :active_pane => :bottom_left, :state => :frozen, :top_left_cell => 'A2' } 9 | @int_0_options = { :x_split => 2, :y_split => 2 } 10 | @options = @nil_options.merge(@int_0_options) 11 | @pane = Axlsx::Pane.new(@options) 12 | end 13 | 14 | 15 | def test_active_pane 16 | assert_raise(ArgumentError) { @pane.active_pane = "10" } 17 | assert_nothing_raised { @pane.active_pane = :top_left } 18 | assert_equal(@pane.active_pane, "topLeft") 19 | end 20 | 21 | def test_state 22 | assert_raise(ArgumentError) { @pane.state = "foo" } 23 | assert_nothing_raised { @pane.state = :frozen_split } 24 | assert_equal(@pane.state, "frozenSplit") 25 | end 26 | 27 | def test_x_split 28 | assert_raise(ArgumentError) { @pane.x_split = "foo´" } 29 | assert_nothing_raised { @pane.x_split = 200 } 30 | assert_equal(@pane.x_split, 200) 31 | end 32 | 33 | def test_y_split 34 | assert_raise(ArgumentError) { @pane.y_split = 'foo' } 35 | assert_nothing_raised { @pane.y_split = 300 } 36 | assert_equal(@pane.y_split, 300) 37 | end 38 | 39 | def test_top_left_cell 40 | assert_raise(ArgumentError) { @pane.top_left_cell = :cell } 41 | assert_nothing_raised { @pane.top_left_cell = "A2" } 42 | assert_equal(@pane.top_left_cell, "A2") 43 | end 44 | 45 | def test_to_xml 46 | doc = Nokogiri::XML.parse(@pane.to_xml_string) 47 | assert_equal(1, doc.xpath("//pane[@ySplit=2][@xSplit='2'][@topLeftCell='A2'][@state='frozen'][@activePane='bottomLeft']").size) 48 | end 49 | def test_to_xml_frozen 50 | pane = Axlsx::Pane.new :state => :frozen, :y_split => 2 51 | doc = Nokogiri::XML(pane.to_xml_string) 52 | assert_equal(1, doc.xpath("//pane[@topLeftCell='A3']").size) 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_pivot_table_cache_definition.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestPivotTableCacheDefinition < Test::Unit::TestCase 4 | def setup 5 | p = Axlsx::Package.new 6 | @ws = p.workbook.add_worksheet 7 | 5.times do 8 | @ws << ["aa","aa","aa","aa"] 9 | end 10 | @pivot_table = @ws.add_pivot_table('G5:G6', 'A1:D5') 11 | @cache_definition = @pivot_table.cache_definition 12 | end 13 | 14 | def test_initialization 15 | assert(@cache_definition.is_a?(Axlsx::PivotTableCacheDefinition), "must create a pivot table cache definition") 16 | assert_equal(@pivot_table, @cache_definition.pivot_table, 'refers back to its pivot table') 17 | end 18 | 19 | def test_pn 20 | assert_equal('pivotCache/pivotCacheDefinition1.xml', @cache_definition.pn) 21 | end 22 | 23 | def test_rId 24 | assert_equal @pivot_table.relationships.for(@cache_definition).Id, @cache_definition.rId 25 | end 26 | 27 | def test_index 28 | assert_equal(0, @cache_definition.index) 29 | end 30 | 31 | def test_cache_id 32 | assert_equal(1, @cache_definition.cache_id) 33 | end 34 | 35 | def test_data_sheet 36 | data_sheet = @ws.clone 37 | data_sheet.name = "Pivot Table Data Source" 38 | @pivot_table.data_sheet = data_sheet 39 | 40 | assert(@cache_definition.to_xml_string.include?(data_sheet.name), "must set the data source correctly") 41 | end 42 | 43 | def test_to_xml_string 44 | schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) 45 | doc = Nokogiri::XML(@cache_definition.to_xml_string) 46 | errors = [] 47 | schema.validate(doc).each do |error| 48 | errors.push error 49 | puts error.message 50 | end 51 | assert(errors.empty?, "error free validation") 52 | end 53 | 54 | end 55 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_protected_range.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | require 'tc_helper.rb' 3 | class TestProtectedRange < Test::Unit::TestCase 4 | def setup 5 | @p = Axlsx::Package.new 6 | @ws = @p.workbook.add_worksheet { |sheet| sheet.add_row [1,2,3,4,5,6,7,8,9] } 7 | end 8 | 9 | def test_initialize_options 10 | assert_nothing_raised {Axlsx::ProtectedRange.new(:sqref => 'A1:B1', :name => "only bob")} 11 | end 12 | 13 | def test_range 14 | r = @ws.protect_range('A1:B1') 15 | assert_equal('A1:B1', r.sqref) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_rich_text.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class RichText < Test::Unit::TestCase 4 | def setup 5 | p = Axlsx::Package.new 6 | @ws = p.workbook.add_worksheet :name => "hmmmz" 7 | p.workbook.styles.add_style :sz => 20 8 | @rt = Axlsx::RichText.new 9 | b = true 10 | (0..26).each do |r| 11 | @rt.add_run "run #{r}, ", :b => (b=!b), :i => !b 12 | end 13 | @row = @ws.add_row [@rt] 14 | @c = @row.first 15 | end 16 | 17 | def test_initialize 18 | assert_equal(@c.value, @rt) 19 | rt_direct = Axlsx::RichText.new('hi', :i => true) 20 | rt_indirect = Axlsx::RichText.new() 21 | rt_indirect.add_run('hi', :i => true) 22 | assert_equal(rt_direct.runs.length, 1) 23 | assert_equal(rt_indirect.runs.length, 1) 24 | row = @ws.add_row [rt_direct, rt_indirect] 25 | assert_equal(row[0].to_xml_string(0,0), row[1].to_xml_string(0,0)) 26 | end 27 | 28 | def test_textruns 29 | runs = @rt.runs 30 | assert_equal(runs.length, 27) 31 | assert_equal(runs.first.b, false) 32 | assert_equal(runs.first.i, true) 33 | assert_equal(runs[1].b, true) 34 | assert_equal(runs[1].i, false) 35 | end 36 | 37 | def test_implicit_richtext 38 | rt = Axlsx::RichText.new('a', :b => true) 39 | row_rt = @ws.add_row [rt] 40 | row_imp = @ws.add_row ['a'] 41 | row_imp[0].b = true 42 | assert_equal(row_rt[0].to_xml_string(0,0), row_imp[0].to_xml_string(0,0)) 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_sheet_calc_pr.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper' 2 | 3 | class TestSheetCalcPr < Test::Unit::TestCase 4 | 5 | def setup 6 | @sheet_calc_pr = Axlsx::SheetCalcPr.new(:full_calc_on_load => false) 7 | end 8 | 9 | def test_full_calc_on_load 10 | assert_equal false, @sheet_calc_pr.full_calc_on_load 11 | assert Axlsx::SheetCalcPr.new.full_calc_on_load 12 | end 13 | 14 | def test_to_xml_string 15 | doc = Nokogiri::XML(@sheet_calc_pr.to_xml_string) 16 | assert_equal 1, doc.xpath('//sheetCalcPr[@fullCalcOnLoad=0]').size 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_sheet_pr.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | 4 | class TestSheetPr < Test::Unit::TestCase 5 | 6 | def setup 7 | worksheet = Axlsx::Package.new.workbook.add_worksheet 8 | @options = { 9 | :sync_horizontal => false, 10 | :sync_vertical => false, 11 | :transition_evaluation => true, 12 | :transition_entry => true, 13 | :published => false, 14 | :filter_mode => true, 15 | :enable_format_conditions_calculation => false, 16 | :code_name => '007', 17 | :sync_ref => 'foo', 18 | :tab_color => 'FFFF6666' 19 | } 20 | @sheet_pr = Axlsx::SheetPr.new(worksheet, @options) 21 | end 22 | 23 | def test_initialization 24 | @options.each do |key, value| 25 | if key==:tab_color 26 | stored_value = @sheet_pr.send(key) 27 | assert_equal Axlsx::Color, stored_value.class 28 | assert_equal value, stored_value.rgb 29 | else 30 | assert_equal value, @sheet_pr.send(key) 31 | end 32 | end 33 | end 34 | 35 | def test_to_xml_string 36 | doc = Nokogiri::XML(@sheet_pr.to_xml_string) 37 | assert_equal(doc.xpath("//sheetPr[@syncHorizontal='0']").size, 1) 38 | assert_equal(doc.xpath("//sheetPr[@syncVertical='0']").size, 1) 39 | assert_equal(doc.xpath("//sheetPr[@transitionEvaluation='1']").size, 1) 40 | assert_equal(doc.xpath("//sheetPr[@transitionEntry='1']").size, 1) 41 | assert_equal(doc.xpath("//sheetPr[@published='0']").size, 1) 42 | assert_equal(doc.xpath("//sheetPr[@filterMode='1']").size, 1) 43 | assert_equal(doc.xpath("//sheetPr[@enableFormatConditionsCalculation='0']").size, 1) 44 | assert_equal(doc.xpath("//sheetPr[@codeName='007']").size, 1) 45 | assert_equal(doc.xpath("//sheetPr[@syncRef='foo']").size, 1) 46 | assert_equal(doc.xpath("//sheetPr/tabColor[@rgb='FFFF6666']").size, 1) 47 | assert_equal(doc.xpath("//sheetPr/pageSetUpPr[@fitToPage='0']").size, 1) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_table_style_info.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestTableStyleInfo < Test::Unit::TestCase 4 | def setup 5 | p = Axlsx::Package.new 6 | @ws = p.workbook.add_worksheet 7 | 40.times do 8 | @ws.add_row %w(aa bb cc dd ee ff gg hh ii jj kk) 9 | end 10 | @table = @ws.add_table(Axlsx::cell_range([@ws.rows.first.cells.first,@ws.rows.last.cells.last], false), :name => 'foo') 11 | @options = { :show_first_column => 1, 12 | :show_last_column => 1, 13 | :show_row_stripes => 1, 14 | :show_column_stripes => 1, 15 | :name => "TableStyleDark4" } 16 | 17 | 18 | end 19 | 20 | def test_initialize 21 | table_style = Axlsx::TableStyleInfo.new @options 22 | @options.each do |key, value| 23 | assert_equal(value, table_style.send(key.to_sym)) 24 | end 25 | end 26 | 27 | def test_boolean_properties 28 | table_style = Axlsx::TableStyleInfo.new 29 | @options.keys.each do |key| 30 | assert_nothing_raised { table_style.send("#{key.to_sym}=", true) } 31 | assert_raises(ArgumentError) { table_style.send(key.to_sym, 'foo') } 32 | end 33 | end 34 | def doc 35 | @doc ||= Nokogiri::XML(Axlsx::TableStyleInfo.new(@options).to_xml_string) 36 | end 37 | 38 | def test_to_xml_string_first_column 39 | assert(doc.xpath('//tableStyleInfo[@showLastColumn=1]')) 40 | end 41 | 42 | def test_to_xml_string_row_stripes 43 | assert(doc.xpath('//tableStyleInfo[@showRowStripes=1]')) 44 | end 45 | 46 | def test_to_xml_string_column_stripes 47 | assert(doc.xpath('//tableStyleInfo[@showColumnStripes=1]')) 48 | end 49 | 50 | def test_to_xml_string_name 51 | assert(doc.xpath("//tableStyleInfo[@name=#{@options[:name]}]")) 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /test/workbook/worksheet/tc_worksheet_hyperlink.rb: -------------------------------------------------------------------------------- 1 | require 'tc_helper.rb' 2 | 3 | class TestWorksheetHyperlink < Test::Unit::TestCase 4 | def setup 5 | p = Axlsx::Package.new 6 | wb = p.workbook 7 | @ws = wb.add_worksheet 8 | @options = { :location => 'https://github.com/randym/axlsx?foo=1&bar=2', :tooltip => 'axlsx', :ref => 'A1', :display => 'AXSLX', :target => :internal } 9 | @a = @ws.add_hyperlink @options 10 | end 11 | 12 | def test_initailize 13 | assert_raise(ArgumentError) { Axlsx::WorksheetHyperlink.new } 14 | end 15 | 16 | def test_location 17 | assert_equal(@options[:location], @a.location) 18 | end 19 | 20 | def test_tooltip 21 | assert_equal(@options[:tooltip], @a.tooltip) 22 | end 23 | 24 | def test_target 25 | assert_equal(@options[:target], @a.instance_values['target']) 26 | end 27 | 28 | def test_display 29 | assert_equal(@options[:display], @a.display) 30 | end 31 | def test_ref 32 | assert_equal(@options[:ref], @a.ref) 33 | end 34 | 35 | def test_to_xml_string_with_non_external 36 | doc = Nokogiri::XML(@ws.to_xml_string) 37 | assert_equal(doc.xpath("//xmlns:hyperlink[@ref='#{@a.ref}']").size, 1) 38 | assert_equal(doc.xpath("//xmlns:hyperlink[@tooltip='#{@a.tooltip}']").size, 1) 39 | assert_equal(doc.xpath("//xmlns:hyperlink[@location='#{@a.location}']").size, 1) 40 | assert_equal(doc.xpath("//xmlns:hyperlink[@display='#{@a.display}']").size, 1) 41 | assert_equal(doc.xpath("//xmlns:hyperlink[@r:id]").size, 0) 42 | end 43 | 44 | def test_to_xml_stirng_with_external 45 | @a.target = :external 46 | doc = Nokogiri::XML(@ws.to_xml_string) 47 | assert_equal(doc.xpath("//xmlns:hyperlink[@ref='#{@a.ref}']").size, 1) 48 | assert_equal(doc.xpath("//xmlns:hyperlink[@tooltip='#{@a.tooltip}']").size, 1) 49 | assert_equal(doc.xpath("//xmlns:hyperlink[@display='#{@a.display}']").size, 1) 50 | assert_equal(doc.xpath("//xmlns:hyperlink[@location='#{@a.location}']").size, 0) 51 | assert_equal(doc.xpath("//xmlns:hyperlink[@r:id='#{@a.relationship.Id}']").size, 1) 52 | end 53 | end 54 | 55 | 56 | --------------------------------------------------------------------------------