From 25ebea9143c136999bdaeb372fb26d2c070ca730 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 14 Oct 2012 13:20:29 +0900 Subject: Refactored to use options parser, accessors and serialization attributes --- lib/axlsx/package.rb | 6 +- lib/axlsx/workbook/defined_name.rb | 25 +- lib/axlsx/workbook/worksheet/pane.rb | 98 ++++--- lib/axlsx/workbook/worksheet/print_options.rb | 38 +-- lib/axlsx/workbook/worksheet/protected_range.rb | 28 +- lib/axlsx/workbook/worksheet/selection.rb | 68 ++--- lib/axlsx/workbook/worksheet/sheet_calc_pr.rb | 32 +-- lib/axlsx/workbook/worksheet/sheet_pr.rb | 16 +- lib/axlsx/workbook/worksheet/sheet_protection.rb | 212 ++++----------- lib/axlsx/workbook/worksheet/sheet_view.rb | 302 +++++---------------- lib/axlsx/workbook/worksheet/table.rb | 34 ++- lib/axlsx/workbook/worksheet/table_style_info.rb | 13 +- lib/axlsx/workbook/worksheet/worksheet.rb | 5 +- lib/axlsx/workbook/worksheet/worksheet_drawing.rb | 2 +- .../workbook/worksheet/worksheet_hyperlink.rb | 6 +- test/workbook/worksheet/tc_pane.rb | 50 +--- test/workbook/worksheet/tc_selection.rb | 57 +--- 17 files changed, 290 insertions(+), 702 deletions(-) diff --git a/lib/axlsx/package.rb b/lib/axlsx/package.rb index 4146420f..829eb199 100644 --- a/lib/axlsx/package.rb +++ b/lib/axlsx/package.rb @@ -3,7 +3,7 @@ module Axlsx # Package is responsible for managing all the bits and peices that Open Office XML requires to make a valid # xlsx document including valdation and serialization. class Package - + include Axlsx::OptionsParser # provides access to the app doc properties for this package # see App @@ -23,9 +23,7 @@ module Axlsx @workbook = nil @core, @app = Core.new, App.new @core.creator = options[:author] || @core.creator - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + parse_options options yield self if block_given? end diff --git a/lib/axlsx/workbook/defined_name.rb b/lib/axlsx/workbook/defined_name.rb index 8a1f57d4..833093fd 100644 --- a/lib/axlsx/workbook/defined_name.rb +++ b/lib/axlsx/workbook/defined_name.rb @@ -49,8 +49,8 @@ module Axlsx # @example # For clarification: LOG10 is always a cell reference, LOG10() is always formula, LOGO1000 can be a defined name that overrides a cell reference. class DefinedName - - + include Axlsx::SerializedAttributes + include Axlsx::OptionsParser include Axlsx::Accessors # creates a new DefinedName. # @param [String] formula - the formula the defined name references @@ -99,10 +99,9 @@ module Axlsx # version of the workbook that is published to or rendered on a Web or application server. def initialize(formula, options={}) @formula = formula - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + parse_options options end + attr_reader :local_sheet_id # The local sheet index (0-based) @@ -115,8 +114,12 @@ module Axlsx string_attr_accessor :short_cut_key, :status_bar, :help, :description, :custom_menu, :comment # boolean attributes that will be added when this class is evaluated - boolean_attr_accessor :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden - + boolean_attr_accessor :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden + + serializable_attributes :short_cut_key, :status_bar, :help, :description, :custom_menu, :comment, + :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden, :name, :local_sheet_id + + attr_reader :name # The name of this defined name. Please refer to the class documentation for more information def name=(value) @@ -129,12 +132,8 @@ module Axlsx def to_xml_string(str='') raise ArgumentError, 'you must specify the name for this defined name. Please read the documentation for Axlsx::DefinedName for more details' unless name - str << '' << @formula str << '' end diff --git a/lib/axlsx/workbook/worksheet/pane.rb b/lib/axlsx/workbook/worksheet/pane.rb index 069d5dd7..6ac87f13 100644 --- a/lib/axlsx/workbook/worksheet/pane.rb +++ b/lib/axlsx/workbook/worksheet/pane.rb @@ -5,7 +5,24 @@ module Axlsx # @note The recommended way to manage the pane options is via SheetView#pane # @see SheetView#pane class Pane - + + include Axlsx::OptionsParser + include Axlsx::SerializedAttributes + # Creates a new {Pane} object + # @option options [Symbol] active_pane Active Pane + # @option options [Symbol] state Split State + # @option options [Cell, String] top_left_cell Top Left Visible Cell + # @option options [Integer] x_split Horizontal Split Position + # @option options [Integer] y_split Vertical Split Position + def initialize(options={}) + #defaults + @active_pane = @state = @top_left_cell = nil + @x_split = @y_split = 0 + parse_options options + end + + serializable_attributes :active_pane, :state, :top_left_cell, :x_split, :y_split + # Active Pane # The pane that is active. # Options are @@ -32,8 +49,8 @@ module Axlsx # @return [Symbol] # default nil attr_reader :active_pane - - + + # Split State # Indicates whether the pane has horizontal / vertical # splits, and whether those splits are frozen. @@ -51,8 +68,7 @@ module Axlsx # @return [Symbol] # default nil attr_reader :state - - + # Top Left Visible Cell # Location of the top left visible cell in the bottom # right pane (when in Left-To-Right mode). @@ -60,8 +76,7 @@ module Axlsx # @return [String] # default nil attr_reader :top_left_cell - - + # Horizontal Split Position # Horizontal position of the split, in 1/20th of a point; 0 (zero) # if none. If the pane is frozen, this value indicates the number @@ -70,8 +85,7 @@ module Axlsx # @return [Integer] # default 0 attr_reader :x_split - - + # Vertical Split Position # Vertical position of the split, in 1/20th of a point; 0 (zero) # if none. If the pane is frozen, this value indicates the number @@ -80,65 +94,49 @@ module Axlsx # @return [Integer] # default 0 attr_reader :y_split - - - # Creates a new {Pane} object - # @option options [Symbol] active_pane Active Pane - # @option options [Symbol] state Split State - # @option options [Cell, String] top_left_cell Top Left Visible Cell - # @option options [Integer] x_split Horizontal Split Position - # @option options [Integer] y_split Vertical Split Position - def initialize(options={}) - #defaults - @active_pane = @state = @top_left_cell = nil - @x_split = @y_split = 0 - - # write options to instance variables - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end - end - - + # @see active_pane - def active_pane=(v); Axlsx::validate_pane_type(v); @active_pane = v end - - + def active_pane=(v) + Axlsx::validate_pane_type(v) + @active_pane = Axlsx::camel(v.to_s, false) + end + # @see state - def state=(v); Axlsx::validate_split_state_type(v); @state = v end - - + def state=(v) + Axlsx::validate_split_state_type(v) + @state = Axlsx::camel(v.to_s, false) + end + # @see top_left_cell def top_left_cell=(v) cell = (v.class == Axlsx::Cell ? v.r_abs : v) - Axlsx::validate_string(cell) - @top_left_cell = cell + Axlsx::validate_string(cell) + @top_left_cell = cell end - - + # @see x_split def x_split=(v); Axlsx::validate_unsigned_int(v); @x_split = v end - - + # @see y_split def y_split=(v); Axlsx::validate_unsigned_int(v); @y_split = v end - - + # Serializes the data validation # @param [String] str # @return [String] def to_xml_string(str = '') - if @state == :frozen && @top_left_cell.nil? + finalize + str << '' + end + private + + def finalize + if @state == 'frozen' && @top_left_cell.nil? row = @y_split || 0 column = @x_split || 0 - @top_left_cell = "#{('A'..'ZZ').to_a[column]}#{row+1}" end - - str << '' end end end diff --git a/lib/axlsx/workbook/worksheet/print_options.rb b/lib/axlsx/workbook/worksheet/print_options.rb index bc177980..cb9bcd1d 100644 --- a/lib/axlsx/workbook/worksheet/print_options.rb +++ b/lib/axlsx/workbook/worksheet/print_options.rb @@ -6,22 +6,9 @@ module Axlsx # @see Worksheet#initialize class PrintOptions - # Whether grid lines should be printed. - # @return [Boolean] - attr_reader :grid_lines - - # Whether row and column headings should be printed. - # @return [Boolean] - attr_reader :headings - - # Whether the content should be centered horizontally on the page. - # @return [Boolean] - attr_reader :horizontal_centered - - # Whether the content should be centered vertically on the page. - # @return [Boolean] - attr_reader :vertical_centered - + include Axlsx::OptionsParser + include Axlsx::SerializedAttributes + include Axlsx::Accessors # Creates a new PrintOptions object # @option options [Boolean] grid_lines Whether grid lines should be printed # @option options [Boolean] headings Whether row and column headings should be printed @@ -32,31 +19,22 @@ module Axlsx set(options) end + serializable_attributes :grid_lines, :headings, :horizontal_centered, :vertical_centered + boolean_attr_accessor :grid_lines, :headings, :horizontal_centered, :vertical_centered + # Set some or all options at once. # @param [Hash] options The options to set (possible keys are :grid_lines, :headings, :horizontal_centered, and :vertical_centered). def set(options) - options.each do |k, v| - send("#{k}=", v) if respond_to? "#{k}=" - end + parse_options options end - # @see grid_lines - def grid_lines=(v); Axlsx::validate_boolean(v); @grid_lines = v; end - # @see headings - def headings=(v); Axlsx::validate_boolean(v); @headings = v; end - # @see horizontal_centered - def horizontal_centered=(v); Axlsx::validate_boolean(v); @horizontal_centered = v; end - # @see vertical_centered - def vertical_centered=(v); Axlsx::validate_boolean(v); @vertical_centered = v; end - # Serializes the page options element. # @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. # @param [String] str # @return [String] def to_xml_string(str = '') str << '' end end diff --git a/lib/axlsx/workbook/worksheet/protected_range.rb b/lib/axlsx/workbook/worksheet/protected_range.rb index 5917ad6e..c58b895d 100644 --- a/lib/axlsx/workbook/worksheet/protected_range.rb +++ b/lib/axlsx/workbook/worksheet/protected_range.rb @@ -4,6 +4,18 @@ module Axlsx # @see Worksheet#protect_range class ProtectedRange + include Axlsx::OptionsParser + include Axlsx::SerializedAttributes + + # Initializes a new protected range object + # @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. + # @option [String] name An optional name for the protected name. + def initialize(options={}) + parse_options options + yield self if block_given? + end + + serializable_attributes :sqref, :name # The reference for the protected range # @return [String] attr_reader :sqref @@ -12,16 +24,6 @@ module Axlsx # @return [String] attr_reader :name - # Initializes a new protected range object - # @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. - # @option [String] name An optional name for the protected name. - def initialize(options={}) - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end - yield self if block_given? - end - # @see sqref def sqref=(v) Axlsx.validate_string(v) @@ -33,14 +35,16 @@ module Axlsx Axlsx.validate_string(v) @name = v end - + # serializes the proteted range # @param [String] str if this string object is provided we append # our output to that object. Use this - it helps limit the number of # objects created during serialization def to_xml_string(str="") attrs = self.instance_values.reject{ |key, value| value == nil } - str << '' + str << '' end end end diff --git a/lib/axlsx/workbook/worksheet/selection.rb b/lib/axlsx/workbook/worksheet/selection.rb index b1ada495..432216b7 100644 --- a/lib/axlsx/workbook/worksheet/selection.rb +++ b/lib/axlsx/workbook/worksheet/selection.rb @@ -5,15 +5,28 @@ module Axlsx # @note The recommended way to manage the selection pane options is via SheetView#add_selection # @see SheetView#add_selection class Selection - + + include Axlsx::OptionsParser + include Axlsx::SerializedAttributes + + # Creates a new {Selection} object + # @option options [Cell, String] active_cell Active Cell Location + # @option options [Integer] active_cell_id Active Cell Index + # @option options [Symbol] pane Pane + # @option options [String] sqref Sequence of References + def initialize(options={}) + @active_cell = @active_cell_id = @pane = @sqref = nil + parse_options options + end + + serializable_attributes :active_cell, :active_cell_id, :pane, :sqref # Active Cell Location # Location of the active cell. # @see type # @return [String] # default nil attr_reader :active_cell - - + # Active Cell Index # 0-based index of the range reference (in the array of references listed in sqref) # containing the active cell. Only used when the selection in sqref is not contiguous. @@ -24,8 +37,7 @@ module Axlsx # @return [Integer] # default nil attr_reader :active_cell_id - - + # Pane # The pane to which this selection belongs. # Options are @@ -52,59 +64,39 @@ module Axlsx # @return [Symbol] # default nil attr_reader :pane - - + # Sequence of References # Range of the selection. Can be non-contiguous set of ranges. # @see type # @return [String] # default nil attr_reader :sqref - - - # Creates a new {Selection} object - # @option options [Cell, String] active_cell Active Cell Location - # @option options [Integer] active_cell_id Active Cell Index - # @option options [Symbol] pane Pane - # @option options [String] sqref Sequence of References - def initialize(options={}) - #defaults - @active_cell = @active_cell_id = @pane = @sqref = nil - - # write options to instance variables - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end - end - - + # @see active_cell def active_cell=(v) cell = (v.class == Axlsx::Cell ? v.r_abs : v) - Axlsx::validate_string(cell) - @active_cell = cell + Axlsx::validate_string(cell) + @active_cell = cell end - - + # @see active_cell_id def active_cell_id=(v); Axlsx::validate_unsigned_int(v); @active_cell_id = v end - - + # @see pane - def pane=(v); Axlsx::validate_pane_type(v); @pane = v end - - + def pane=(v) + Axlsx::validate_pane_type(v) + @pane = Axlsx::camel(v, false) + end + # @see sqref def sqref=(v); Axlsx::validate_string(v); @sqref = v end - - + # Serializes the data validation # @param [String] str # @return [String] def to_xml_string(str = '') str << '' end end diff --git a/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb b/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb index baff512d..88ada9ae 100644 --- a/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +++ b/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb @@ -3,33 +3,20 @@ module Axlsx # the SheetCalcPr object for the worksheet # This object contains calculation properties for the worksheet. class SheetCalcPr - + include Axlsx::OptionsParser + include Axlsx::SerializedAttributes + include Axlsx::Accessors # creates a new SheetCalcPr # @param [Hash] options Options for this object # @option [Boolean] full_calc_on_load @see full_calc_on_load def initialize(options={}) @full_calc_on_load = true - options.each do |key, value| - self.send("#{key}=", value) if self.respond_to?("#{key}=") - end + parse_options options end - # Indicates whether the application should do a full calculate on - # load due to contents on this sheet. After load and successful cal,c - # the application shall set this value to false. Set this to true - # when the application should calculate the workbook on load. - # @return [Boolean] - def full_calc_on_load - @full_calc_on_load - end + boolean_attr_accessor :full_calc_on_load - # specify the full_calc_on_load value - # @param [Boolean] value - # @see full_calc_on_load - def full_calc_on_load=(value) - Axlsx.validate_boolean(value) - @full_calc_on_load = value - end + serializable_attributes :full_calc_on_load # Serialize the object # @param [String] str the string to append this objects serialized @@ -38,12 +25,5 @@ module Axlsx def to_xml_string(str='') str << "" end - - private - - def serialized_attributes - instance_values.map { |key, value| "#{Axlsx.camel(key, false)}='#{value}'" }.join(' ') - end - end end diff --git a/lib/axlsx/workbook/worksheet/sheet_pr.rb b/lib/axlsx/workbook/worksheet/sheet_pr.rb index aa737707..f271419b 100644 --- a/lib/axlsx/workbook/worksheet/sheet_pr.rb +++ b/lib/axlsx/workbook/worksheet/sheet_pr.rb @@ -2,7 +2,7 @@ module Axlsx # The SheetPr class manages serialization fo a worksheet's sheetPr element. class SheetPr - + include Axlsx::OptionsParser include Axlsx::Accessors include Axlsx::SerializedAttributes @@ -33,10 +33,7 @@ module Axlsx def initialize(worksheet, options={}) raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) @worksheet = worksheet - options.each do |key, value| - attr = "#{key}=" - self.send(attr, value) if self.respond_to?(attr) - end + parse_options options end # The worksheet these properties apply to! @@ -61,15 +58,6 @@ module Axlsx private - # def serialized_attributes(str = '') - #instance_values.each do |key, value| - #unless %(worksheet page_setup_pr).include? key - #str << "#{Axlsx.camel(key, false)}='#{value}' " - #end - #end - #str - #end - def update_properties page_setup_pr.fit_to_page = worksheet.fit_to_page? if worksheet.auto_filter.columns.size > 0 diff --git a/lib/axlsx/workbook/worksheet/sheet_protection.rb b/lib/axlsx/workbook/worksheet/sheet_protection.rb index 104be53b..a472ec55 100644 --- a/lib/axlsx/workbook/worksheet/sheet_protection.rb +++ b/lib/axlsx/workbook/worksheet/sheet_protection.rb @@ -4,110 +4,9 @@ module Axlsx # The SheetProtection object manages worksheet protection options per sheet. class SheetProtection - # If 1 or true then AutoFilters should not be allowed to operate when the sheet is protected. - # If 0 or false then AutoFilters should be allowed to operate when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :auto_filter - - # If 1 or true then deleting columns should not be allowed when the sheet is protected. - # If 0 or false then deleting columns should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :delete_columns - - # If 1 or true then deleting rows should not be allowed when the sheet is protected. - # If 0 or false then deleting rows should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :delete_rows - - # If 1 or true then formatting cells should not be allowed when the sheet is protected. - # If 0 or false then formatting cells should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :format_cells - - # If 1 or true then formatting columns should not be allowed when the sheet is protected. - # If 0 or false then formatting columns should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :format_columns - - # If 1 or true then formatting rows should not be allowed when the sheet is protected. - # If 0 or false then formatting rows should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :format_rows - - # If 1 or true then inserting columns should not be allowed when the sheet is protected. - # If 0 or false then inserting columns should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :insert_columns - - # If 1 or true then inserting hyperlinks should not be allowed when the sheet is protected. - # If 0 or false then inserting hyperlinks should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :insert_hyperlinks - - # If 1 or true then inserting rows should not be allowed when the sheet is protected. - # If 0 or false then inserting rows should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :insert_rows - - # If 1 or true then editing of objects should not be allowed when the sheet is protected. - # If 0 or false then objects are allowed to be edited when the sheet is protected. - # @return [Boolean] - # default false - attr_reader :objects - - # If 1 or true then PivotTables should not be allowed to operate when the sheet is protected. - # If 0 or false then PivotTables should be allowed to operate when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :pivot_tables - - # Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm - # @return [String] - attr_reader :salt_value - - # If 1 or true then Scenarios should not be edited when the sheet is protected. - # If 0 or false then Scenarios are allowed to be edited when the sheet is protected. - # @return [Boolean] - # default false - attr_reader :scenarios - - # If 1 or true then selection of locked cells should not be allowed when the sheet is protected. - # If 0 or false then selection of locked cells should be allowed when the sheet is protected. - # @return [Boolean] - # default false - attr_reader :select_locked_cells - - # If 1 or true then selection of unlocked cells should not be allowed when the sheet is protected. - # If 0 or false then selection of unlocked cells should be allowed when the sheet is protected. - # @return [Boolean] - # default false - attr_reader :select_unlocked_cells - - # If 1 or true then the sheet is protected. - # If 0 or false then the sheet is not protected. - # @return [Boolean] - # default true - attr_reader :sheet - - # If 1 or true then sorting should not be allowed when the sheet is protected. - # If 0 or false then sorting should be allowed when the sheet is protected. - # @return [Boolean] - # default true - attr_reader :sort - - # Password hash - # @return [String] - # default nil - attr_reader :password + include Axlsx::OptionsParser + include Axlsx::SerializedAttributes + include Axlsx::Accessors # Creates a new SheetProtection instance # @option options [Boolean] sheet @see SheetProtection#sheet @@ -127,64 +26,68 @@ module Axlsx # @option options [Boolean] pivot_tables @see SheetProtection#pivot_tables # @option options [Boolean] select_unlocked_cells @see SheetProtection#select_unlocked_cells # @option options [String] password. The password required for unlocking. @see SheetProtection#password= - # @option options [Boolean] objects @see SheetProtection#objects def initialize(options={}) @objects = @scenarios = @select_locked_cells = @select_unlocked_cells = false @sheet = @format_cells = @format_rows = @format_columns = @insert_columns = @insert_rows = @insert_hyperlinks = @delete_columns = @delete_rows = @sort = @auto_filter = @pivot_tables = true @password = nil + parse_options options + end - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + boolean_attr_accessor :sheet, :objects, :scenarios, :format_cells, :format_columns, :format_rows, + :insert_columns, :insert_rows, :insert_hyperlinks, :delete_columns, :delete_rows, + :select_locked_cells, :sort, :auto_filter, :pivot_tables, :select_unlocked_cells + + serializable_attributes :sheet, :objects, :scenarios, :format_cells, :format_columns, :format_rows, + :insert_columns, :insert_rows, :insert_hyperlinks, :delete_columns, :delete_rows, + :select_locked_cells, :sort, :auto_filter, :pivot_tables, :select_unlocked_cells, :salt, :password + + # Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm + # @return [String] + attr_reader :salt_value + + # If 1 or true then sorting should not be allowed when the sheet is protected. + # If 0 or false then sorting should be allowed when the sheet is protected. + # @return [Boolean] + # default true + attr_reader :sort + + # Password hash + # @return [String] + # default nil + attr_reader :password + + # This block is intended to implement the salt_value, hash_value and spin count as per the ECMA-376 standard. + # However, it does not seem to actually work in EXCEL - instead they are using their old retro algorithm shown below + # defined in the transitional portion of the speck. I am leaving this code in in the hope that someday Ill be able to + # figure out why it does not work, and if Excel even supports it. + # def propper_password=(v) + # @algorithm_name = v == nil ? nil : 'SHA-1' + # @salt_value = @spin_count = @hash_value = v if v == nil + # return if v == nil + # require 'digest/sha1' + # @spin_count = 10000 + # @salt_value = Digest::SHA1.hexdigest(rand(36**8).to_s(36)) + # @spin_count.times do |count| + # @hash_value = Digest::SHA1.hexdigest((@hash_value ||= (@salt_value + v.to_s)) + Array(count).pack('V')) + # end + # end + + # encodes password for protection locking + def password=(v) + return if v == nil + @password = create_password_hash(v) end + # Serialize the object + # @param [String] str + # @return [String] + def to_xml_string(str = '') + str << '' + end - # create validating setters for boolean values - # @return [Boolean] - [:sheet, :objects, :scenarios, :select_locked_cells, :sort, - :select_unlocked_cells, :format_cells, :format_rows, :format_columns, - :insert_columns, :insert_rows, :insert_hyperlinks, :delete_columns, - :delete_rows, :auto_filter, :pivot_tables].each do |f_name| - define_method "#{f_name.to_s}=".to_sym do |v| - Axlsx::validate_boolean(v) - instance_variable_set "@#{f_name.to_s}".to_sym, v - end - end - - # This block is intended to implement the salt_value, hash_value and spin count as per the ECMA-376 standard. - # However, it does not seem to actually work in EXCEL - instead they are using their old retro algorithm shown below - # defined in the transitional portion of the speck. I am leaving this code in in the hope that someday Ill be able to - # figure out why it does not work, and if Excel even supports it. -# def propper_password=(v) -# @algorithm_name = v == nil ? nil : 'SHA-1' -# @salt_value = @spin_count = @hash_value = v if v == nil -# return if v == nil -# require 'digest/sha1' -# @spin_count = 10000 -# @salt_value = Digest::SHA1.hexdigest(rand(36**8).to_s(36)) -# @spin_count.times do |count| -# @hash_value = Digest::SHA1.hexdigest((@hash_value ||= (@salt_value + v.to_s)) + Array(count).pack('V')) -# end -# end - - - - # encodes password for protection locking - def password=(v) - return if v == nil - @password = create_password_hash(v) - end - - # Serialize the object - # @param [String] str - # @return [String] - def to_xml_string(str = '') - str << '' - end - - private + private # Creates a password hash for a given password # @return [String] def create_password_hash(password) @@ -196,7 +99,6 @@ module Axlsx password_as_string[2..3] + password_as_string[0..1] end - # Encodes a given password # Based on the algorithm provided by Daniel Rentz of OpenOffice. # http://www.openoffice.org/sc/excelfileformat.pdf, Revision 1.42, page 115 (21.05.2012) diff --git a/lib/axlsx/workbook/worksheet/sheet_view.rb b/lib/axlsx/workbook/worksheet/sheet_view.rb index 02dced64..434f7b7a 100644 --- a/lib/axlsx/workbook/worksheet/sheet_view.rb +++ b/lib/axlsx/workbook/worksheet/sheet_view.rb @@ -5,10 +5,54 @@ module Axlsx # @note The recommended way to manage the sheet view is via Worksheet#sheet_view # @see Worksheet#sheet_view class SheetView - + + include Axlsx::OptionsParser + include Axlsx::Accessors + include Axlsx::SerializedAttributes + + # Creates a new {SheetView} object + # @option options [Integer] color_id Color Id + # @option options [Boolean] default_grid_color Default Grid Color + # @option options [Boolean] right_to_left Right To Left + # @option options [Boolean] show_formulas Show Formulas + # @option options [Boolean] show_grid_lines Show Grid Lines + # @option options [Boolean] show_outline_symbols Show Outline Symbols + # @option options [Boolean] show_row_col_headers Show Headers + # @option options [Boolean] show_ruler Show Ruler + # @option options [Boolean] show_white_space Show White Space + # @option options [Boolean] show_zeros Show Zero Values + # @option options [Boolean] tab_selected Sheet Tab Selected + # @option options [String, Cell] top_left_cell Top Left Visible Cell + # @option options [Symbol] view View Type + # @option options [Boolean] window_protection Window Protection + # @option options [Integer] workbook_view_id Workbook View Index + # @option options [Integer] zoom_scale + # @option options [Integer] zoom_scale_normal Zoom Scale Normal View + # @option options [Integer] zoom_scale_page_layout_view Zoom Scale Page Layout View + # @option options [Integer] zoom_scale_sheet_layout_view Zoom Scale Page Break Preview + def initialize(options={}) + #defaults + @color_id = @top_left_cell = @pane = nil + @right_to_left = @show_formulas = @show_outline_symbols = @show_white_space = @tab_selected = @window_protection = false + @default_grid_color = @show_grid_lines = @show_row_col_headers = @show_ruler = @show_zeros = true + @zoom_scale = 100 + @zoom_scale_normal = @zoom_scale_page_layout_view = @zoom_scale_sheet_layout_view = @workbook_view_id = 0 + @selections = {} + parse_options options + end + + boolean_attr_accessor :default_grid_color, :right_to_left, :show_formulas, :show_grid_lines, + :show_row_col_headers, :show_ruler, :show_white_space, :show_zeros, :tab_selected, :window_protection, :show_outline_symbols + + serializable_attributes :default_grid_color, :right_to_left, :show_formulas, :show_grid_lines, + :show_row_col_headers, :show_ruler, :show_white_space, :show_zeros, :tab_selected, :window_protection, :show_outline_symbols, + :zoom_scale_sheet_layout_view, :zoom_scale_page_layout_view, :zoom_scale_normal, :workbook_view_id, + :view, :top_left_cell, :color_id, :zoom_scale + + # instance values that must be serialized as their own elements - e.g. not attributes. CHILD_ELEMENTS = [ :pane, :selections ] - + # The pane object for the sheet view # @return [Pane] # @see [Pane] @@ -17,7 +61,7 @@ module Axlsx yield @pane if block_given? @pane end - + # A hash of selection objects keyed by pane type associated with this sheet view. # @return [Hash] attr_reader :selections @@ -32,116 +76,7 @@ module Axlsx # @return [Integer] # default nil attr_reader :color_id - - - # Default Grid Color - # Flag indicating that the consuming application - # should use the default grid lines color - # (system dependent). Overrides any color - # specified in colorId. - # @see type - # @return [Boolean] - # default true - attr_reader :default_grid_color - - - # Right To Left - # Flag indicating whether the sheet is in - # 'right to left' display mode. When in this - # mode, Column A is on the far right, Column B ; - # is one column left of Column A, and so on. Also, - # information in cells is displayed in the Right - # to Left format. - # @see type - # @return [Boolean] - # default false - attr_reader :right_to_left - - - # Show Formulas - # Flag indicating whether this sheet should - # display formulas. - # @see type - # @return [Boolean] - # default false - attr_reader :show_formulas - - - # Show Grid Lines - # Flag indicating whether this sheet - # should display gridlines. - # @see type - # @return [Boolean] - # default true - attr_reader :show_grid_lines - - - # Show Outline Symbols - # Flag indicating whether the sheet has outline - # symbols visible. This flag shall always override - # SheetPr element's outlinePr child element - # whose attribute is named showOutlineSymbols - # when there is a conflict. - # @see type - # @return [Boolean] - # default false - attr_reader :show_outline_symbols - - - # Show Headers - # Flag indicating whether the sheet should - # display row and column headings. - # @see type - # @return [Boolean] - # default true - attr_reader :show_row_col_headers - - - # Show Ruler - # Show the ruler in Page Layout View. - # @see type - # @return [Boolean] - # default true - attr_reader :show_ruler - - - # Show White Space - # Flag indicating whether page layout - # view shall display margins. False means - # do not display left, right, top (header), - # and bottom (footer) margins (even when - # there is data in the header or footer). - # @see type - # @return [Boolean] - # default false - attr_reader :show_white_space - - - # Show Zero Values - # Flag indicating whether the window should - # show 0 (zero) in cells containing zero value. - # When false, cells with zero value appear - # blank instead of showing the number zero. - # @see type - # @return [Boolean] - # default true - attr_reader :show_zeros - - - # Sheet Tab Selected - # Flag indicating whether this sheet is selected. - # When only 1 sheet is selected and active, this - # value should be in synch with the activeTab value. - # In case of a conflict, the Start Part setting - # wins and sets the active sheet tab. Multiple - # sheets can be selected, but only one sheet shall - # be active at one time. - # @see type - # @return [Boolean] - # default false - attr_reader :tab_selected - - + # Top Left Visible Cell # Location of the top left visible cell Location # of the top left visible cell in the bottom right @@ -162,19 +97,7 @@ module Axlsx # @return [Symbol] # default :normal attr_reader :view - - - # Window Protection - # Flag indicating whether the panes in the window - # are locked due to workbook protection. - # This is an option when the workbook structure is - # protected. - # @see type - # @return [Boolean] - # default true - attr_reader :window_protection - - + # Workbook View Index # Zero-based index of this workbook view, pointing # to a workbookView element in the bookViews collection. @@ -182,8 +105,7 @@ module Axlsx # @return [Integer] # default 0 attr_reader :workbook_view_id - - + # Zoom Scale # Window zoom magnification for current view # representing percent values. This attribute @@ -195,8 +117,8 @@ module Axlsx # @return [Integer] # default 100 attr_reader :zoom_scale - - + + # Zoom Scale Normal View # Zoom magnification to use when in normal view, # representing percent values. This attribute is @@ -208,8 +130,8 @@ module Axlsx # @return [Integer] # default 0 attr_reader :zoom_scale_normal - - + + # Zoom Scale Page Layout View # Zoom magnification to use when in page layout # view, representing percent values. This attribute @@ -221,8 +143,8 @@ module Axlsx # @return [Integer] # default 0 attr_reader :zoom_scale_page_layout_view - - + + # Zoom Scale Page Break Preview # Zoom magnification to use when in page break # preview, representing percent values. This @@ -235,43 +157,7 @@ module Axlsx # @return [Integer] # default 0 attr_reader :zoom_scale_sheet_layout_view - - - # Creates a new {SheetView} object - # @option options [Integer] color_id Color Id - # @option options [Boolean] default_grid_color Default Grid Color - # @option options [Boolean] right_to_left Right To Left - # @option options [Boolean] show_formulas Show Formulas - # @option options [Boolean] show_grid_lines Show Grid Lines - # @option options [Boolean] show_outline_symbols Show Outline Symbols - # @option options [Boolean] show_row_col_headers Show Headers - # @option options [Boolean] show_ruler Show Ruler - # @option options [Boolean] show_white_space Show White Space - # @option options [Boolean] show_zeros Show Zero Values - # @option options [Boolean] tab_selected Sheet Tab Selected - # @option options [String, Cell] top_left_cell Top Left Visible Cell - # @option options [Symbol] view View Type - # @option options [Boolean] window_protection Window Protection - # @option options [Integer] workbook_view_id Workbook View Index - # @option options [Integer] zoom_scale_normal Zoom Scale Normal View - # @option options [Integer] zoom_scale_page_layout_view Zoom Scale Page Layout View - # @option options [Integer] zoom_scale_sheet_layout_view Zoom Scale Page Break Preview - def initialize(options={}) - #defaults - @color_id = @top_left_cell = @pane = nil - @right_to_left = @show_formulas = @show_outline_symbols = @show_white_space = @tab_selected = @window_protection = false - @default_grid_color = @show_grid_lines = @show_row_col_headers = @show_ruler = @show_zeros = true - @zoom_scale = 100 - @zoom_scale_normal = @zoom_scale_page_layout_view = @zoom_scale_sheet_layout_view = @workbook_view_id = 0 - @selections = {} - - # write options to instance variables - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end - end - - + # Adds a new selection # param [Symbol] pane # param [Hash] options @@ -279,94 +165,42 @@ module Axlsx def add_selection(pane, options = {}) @selections[pane] = Selection.new(options.merge(:pane => pane)) end - + # @see color_id def color_id=(v); Axlsx::validate_unsigned_int(v); @color_id = v end - - - # @see default_grid_color - def default_grid_color=(v); Axlsx::validate_boolean(v); @default_grid_color = v end - - - # @see right_to_left - def right_to_left=(v); Axlsx::validate_boolean(v); @right_to_left = v end - - - # @see show_formulas - def show_formulas=(v); Axlsx::validate_boolean(v); @show_formulas = v end - - - # @see show_grid_lines - def show_grid_lines=(v); Axlsx::validate_boolean(v); @show_grid_lines = v end - - - # @see show_outline_symbols - def show_outline_symbols=(v); Axlsx::validate_boolean(v); @show_outline_symbols = v end - - - # @see show_row_col_headers - def show_row_col_headers=(v); Axlsx::validate_boolean(v); @show_row_col_headers = v end - - - # @see show_ruler - def show_ruler=(v); Axlsx::validate_boolean(v); @show_ruler = v end - - - # @see show_white_space - def show_white_space=(v); Axlsx::validate_boolean(v); @show_white_space = v end - - - # @see show_zeros - def show_zeros=(v); Axlsx::validate_boolean(v); @show_zeros = v end - - - # @see tab_selected - def tab_selected=(v); Axlsx::validate_boolean(v); @tab_selected = v end - - + # @see top_left_cell def top_left_cell=(v) cell = (v.class == Axlsx::Cell ? v.r_abs : v) Axlsx::validate_string(cell) - @top_left_cell = cell + @top_left_cell = cell end - - + # @see view def view=(v); Axlsx::validate_sheet_view_type(v); @view = v end - - - # @see window_protection - def window_protection=(v); Axlsx::validate_boolean(v); @window_protection = v end - - + # @see workbook_view_id def workbook_view_id=(v); Axlsx::validate_unsigned_int(v); @workbook_view_id = v end - - + # @see zoom_scale def zoom_scale=(v); Axlsx::validate_scale_0_10_400(v); @zoom_scale = v end - - + # @see zoom_scale_normal def zoom_scale_normal=(v); Axlsx::validate_scale_0_10_400(v); @zoom_scale_normal = v end - - + # @see zoom_scale_page_layout_view def zoom_scale_page_layout_view=(v); Axlsx::validate_scale_0_10_400(v); @zoom_scale_page_layout_view = v end - - + # @see zoom_scale_sheet_layout_view def zoom_scale_sheet_layout_view=(v); Axlsx::validate_scale_0_10_400(v); @zoom_scale_sheet_layout_view = v end - - + # Serializes the data validation # @param [String] str # @return [String] def to_xml_string(str = '') str << '' str << '' @pane.to_xml_string(str) if @pane @selections.each do |key, selection| diff --git a/lib/axlsx/workbook/worksheet/table.rb b/lib/axlsx/workbook/worksheet/table.rb index 424bb73b..dce1a40e 100644 --- a/lib/axlsx/workbook/worksheet/table.rb +++ b/lib/axlsx/workbook/worksheet/table.rb @@ -5,18 +5,7 @@ module Axlsx # @see README for examples class Table - - # The reference to the table data - # @return [String] - attr_reader :ref - - # The name of the table. - # @return [String] - attr_reader :name - - # The style for the table. - # @return [TableStyle] - attr_reader :style + include Axlsx::OptionsParser # Creates a new Table object # @param [String] ref The reference to the table data like 'A1:G24'. @@ -30,12 +19,22 @@ module Axlsx @sheet.workbook.tables << self @table_style_info = TableStyleInfo.new(options[:style_info]) if options[:style_info] @name = "Table#{index+1}" - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + parse_options options yield self if block_given? end + # The reference to the table data + # @return [String] + attr_reader :ref + + # The name of the table. + # @return [String] + attr_reader :name + + # The style for the table. + # @return [TableStyle] + attr_reader :style + # The index of this chart in the workbooks charts collection # @return [Integer] def index @@ -63,7 +62,7 @@ module Axlsx @name = v end end - + # TableStyleInfo for the table. # initialization can be fed via the :style_info option def table_style_info @@ -83,8 +82,7 @@ module Axlsx str << '' end str << '' - #TODO implement tableStyleInfo - table_style_info.to_xml_string(str) # '' + table_style_info.to_xml_string(str) str << '' end diff --git a/lib/axlsx/workbook/worksheet/table_style_info.rb b/lib/axlsx/workbook/worksheet/table_style_info.rb index a9e3d8b7..0e41ea50 100644 --- a/lib/axlsx/workbook/worksheet/table_style_info.rb +++ b/lib/axlsx/workbook/worksheet/table_style_info.rb @@ -3,7 +3,8 @@ module Axlsx # The table style info class manages style attributes for defined tables in # a worksheet class TableStyleInfo - + include Axlsx::OptionsParser + include Axlsx::SerializedAttributes include Axlsx::Accessors # creates a new TableStyleInfo instance # @param [Hash] options @@ -20,13 +21,13 @@ module Axlsx def initialize(options = {}) initialize_defaults @name = 'TableStyleMedium9' - options.each do |k, v| - send("#{k}=", v) if respond_to? "#{k}=" - end + parse_options options end # boolean attributes for this object boolean_attr_accessor :show_first_column, :show_last_column, :show_row_stripes, :show_column_stripes + serializable_attributes :show_first_column, :show_last_column, :show_row_stripes, :show_column_stripes, + :name # Initialize all the values to false as Excel requires them to # explicitly be disabled or all will show. @@ -43,9 +44,7 @@ module Axlsx # @param [String] str the string to contact this objects serialization to. def to_xml_string(str = '') str << '' end end diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 02b0d049..6a32e881 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -3,6 +3,7 @@ module Axlsx # The Worksheet class represents a worksheet in the workbook. class Worksheet + include Axlsx::OptionsParser # definition of characters which are less than the maximum width of 0-9 in the default font for use in String#count. # This is used for autowidth calculations @@ -24,9 +25,7 @@ module Axlsx @sheet_protection = nil initialize_page_options(options) - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + parse_options options end # Initalizes page margin, setup and print options diff --git a/lib/axlsx/workbook/worksheet/worksheet_drawing.rb b/lib/axlsx/workbook/worksheet/worksheet_drawing.rb index 6ace16e1..9deeeec3 100644 --- a/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +++ b/lib/axlsx/workbook/worksheet/worksheet_drawing.rb @@ -10,7 +10,7 @@ module Axlsx # @param [Worksheet] worksheet def initialize(worksheet) raise ArgumentError, 'you must provide a worksheet' unless worksheet.is_a?(Worksheet) - @worksheet = worksheet + @worksheet = worksheet @drawing = nil end diff --git a/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb b/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb index 4807d58d..830698cc 100644 --- a/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +++ b/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb @@ -3,7 +3,7 @@ module Axlsx # A worksheet hyperlink object. Note that this is not the same as a drawing hyperlink object. class WorksheetHyperlink - + include Axlsx::OptionsParser include Axlsx::Accessors include Axlsx::SerializedAttributes # Creates a new hyperlink object. @@ -19,9 +19,7 @@ module Axlsx DataTypeValidator.validate "Hyperlink.worksheet", [Worksheet], worksheet @worksheet = worksheet @target = :external - options.each do |o| - self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + parse_options options yield self if block_given? end diff --git a/test/workbook/worksheet/tc_pane.rb b/test/workbook/worksheet/tc_pane.rb index b11f6534..fff0bf7a 100644 --- a/test/workbook/worksheet/tc_pane.rb +++ b/test/workbook/worksheet/tc_pane.rb @@ -7,61 +7,21 @@ class TestPane < Test::Unit::TestCase #inverse defaults for booleans @nil_options = { :active_pane => :bottom_left, :state => :frozen, :top_left_cell => 'A2' } @int_0_options = { :x_split => 2, :y_split => 2 } - - @string_options = { :top_left_cell => 'A2' } - @integer_options = { :x_split => 2, :y_split => 2 } - @symbol_options = { :active_pane => :bottom_left, :state => :frozen } - - @options = @nil_options.merge(@int_0_options) - + @options = @nil_options.merge(@int_0_options) @pane = Axlsx::Pane.new(@options) end - - def test_initialize - pane = Axlsx::Pane.new - - @nil_options.each do |key, value| - assert_equal(nil, pane.send(key.to_sym), "initialized default #{key} should be nil") - assert_equal(value, @pane.send(key.to_sym), "initialized options #{key} should be #{value}") - end - - @int_0_options.each do |key, value| - assert_equal(0, pane.send(key.to_sym), "initialized default #{key} should be 0") - assert_equal(value, @pane.send(key.to_sym), "initialized options #{key} should be #{value}") - end - end - - def test_string_attribute_validation - @string_options.each do |key, value| - assert_raise(ArgumentError, "#{key} must be string") { @pane.send("#{key}=".to_sym, :symbol) } - assert_nothing_raised { @pane.send("#{key}=".to_sym, "foo") } - end - end - - def test_symbol_attribute_validation - @symbol_options.each do |key, value| - assert_raise(ArgumentError, "#{key} must be symbol") { @pane.send("#{key}=".to_sym, "foo") } - assert_nothing_raised { @pane.send("#{key}=".to_sym, value) } - end - end - - def test_integer_attribute_validation - @integer_options.each do |key, value| - assert_raise(ArgumentError, "#{key} must be integer") { @pane.send("#{key}=".to_sym, "foo") } - assert_nothing_raised { @pane.send("#{key}=".to_sym, value) } - end - end - + + def test_active_pane assert_raise(ArgumentError) { @pane.active_pane = "10" } assert_nothing_raised { @pane.active_pane = :top_left } - assert_equal(@pane.active_pane, :top_left) + assert_equal(@pane.active_pane, "topLeft") end def test_state assert_raise(ArgumentError) { @pane.state = "foo" } assert_nothing_raised { @pane.state = :frozen_split } - assert_equal(@pane.state, :frozen_split) + assert_equal(@pane.state, "frozenSplit") end def test_x_split diff --git a/test/workbook/worksheet/tc_selection.rb b/test/workbook/worksheet/tc_selection.rb index 1b053c2f..696b67eb 100644 --- a/test/workbook/worksheet/tc_selection.rb +++ b/test/workbook/worksheet/tc_selection.rb @@ -3,70 +3,34 @@ require 'tc_helper.rb' class TestSelection < Test::Unit::TestCase def setup - @nil_options = { :active_cell => 'A2', :active_cell_id => 1, :pane => :top_left, :sqref => 'A2' } - @options = @nil_options - - @string_options = { :active_cell => 'A2', :sqref => 'A2' } - @integer_options = { :active_cell_id => 1 } - @symbol_options = { :pane => :top_left } - + @options = { :active_cell => 'A2', :active_cell_id => 1, :pane => :top_left, :sqref => 'A2' } @selection = Axlsx::Selection.new(@options) end - - def test_initialize - selection = Axlsx::Selection.new - - @nil_options.each do |key, value| - assert_equal(nil, selection.send(key.to_sym), "initialized default #{key} should be nil") - assert_equal(value, @selection.send(key.to_sym), "initialized options #{key} should be #{value}") - end - end - - def test_string_attribute_validation - @string_options.each do |key, value| - assert_raise(ArgumentError, "#{key} must be string") { @selection.send("#{key}=".to_sym, :symbol) } - assert_nothing_raised { @selection.send("#{key}=".to_sym, "foo") } - end - end - - def test_symbol_attribute_validation - @symbol_options.each do |key, value| - assert_raise(ArgumentError, "#{key} must be symbol") { @selection.send("#{key}=".to_sym, "foo") } - assert_nothing_raised { @selection.send("#{key}=".to_sym, value) } - end - end - - def test_integer_attribute_validation - @integer_options.each do |key, value| - assert_raise(ArgumentError, "#{key} must be integer") { @selection.send("#{key}=".to_sym, "foo") } - assert_nothing_raised { @selection.send("#{key}=".to_sym, value) } - end - end - + def test_active_cell assert_raise(ArgumentError) { @selection.active_cell = :active_cell } assert_nothing_raised { @selection.active_cell = "F5" } assert_equal(@selection.active_cell, "F5") end - + def test_active_cell_id assert_raise(ArgumentError) { @selection.active_cell_id = "foo" } assert_nothing_raised { @selection.active_cell_id = 11 } assert_equal(@selection.active_cell_id, 11) end - + def test_pane assert_raise(ArgumentError) { @selection.pane = "foo´" } assert_nothing_raised { @selection.pane = :bottom_right } - assert_equal(@selection.pane, :bottom_right) + assert_equal(@selection.pane, "bottomRight") end - + def test_sqref assert_raise(ArgumentError) { @selection.sqref = :sqref } assert_nothing_raised { @selection.sqref = "G32" } assert_equal(@selection.sqref, "G32") end - + def test_to_xml p = Axlsx::Package.new @ws = p.workbook.add_worksheet :name => "sheetview" @@ -76,18 +40,15 @@ class TestSelection < Test::Unit::TestCase vs.add_selection(:bottom_left, { :active_cell => 'E55', :sqref => 'E55' }) vs.add_selection(:bottom_right, { :active_cell => 'I57', :sqref => 'I57' }) end - + doc = Nokogiri::XML.parse(@ws.to_xml_string) - + assert_equal(1, doc.xpath("//xmlns:worksheet/xmlns:sheetViews/xmlns:sheetView/xmlns:selection[@sqref='B2'][@pane='topLeft'][@activeCell='B2']").size) assert doc.xpath("//xmlns:worksheet/xmlns:sheetViews/xmlns:sheetView/xmlns:selection[@sqref='B2'][@pane='topLeft'][@activeCell='B2']") - assert_equal(1, doc.xpath("//xmlns:worksheet/xmlns:sheetViews/xmlns:sheetView/xmlns:selection[@sqref='I10'][@pane='topRight'][@activeCell='I10']").size) assert doc.xpath("//xmlns:worksheet/xmlns:sheetViews/xmlns:sheetView/xmlns:selection[@sqref='I10'][@pane='topRight'][@activeCell='I10']") - assert_equal(1, doc.xpath("//xmlns:worksheet/xmlns:sheetViews/xmlns:sheetView/xmlns:selection[@sqref='E55'][@pane='bottomLeft'][@activeCell='E55']").size) assert doc.xpath("//xmlns:worksheet/xmlns:sheetViews/xmlns:sheetView/xmlns:selection[@sqref='E55'][@pane='bottomLeft'][@activeCell='E55']") - assert_equal(1, doc.xpath("//xmlns:worksheet/xmlns:sheetViews/xmlns:sheetView/xmlns:selection[@sqref='I57'][@pane='bottomRight'][@activeCell='I57']").size) assert doc.xpath("//xmlns:worksheet/xmlns:sheetViews/xmlns:sheetView/xmlns:selection[@sqref='I57'][@pane='bottomRight'][@activeCell='I57']") end -- cgit v1.2.3