write_xlsx 0.64.1 → 0.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.rdoc +10 -1
 - data/examples/conditional_format.rb +251 -18
 - data/examples/demo.rb +2 -3
 - data/examples/macros.rb +42 -0
 - data/examples/outline_collapsed.rb +160 -0
 - data/examples/republic.png +0 -0
 - data/examples/shape3.rb +2 -2
 - data/examples/shape4.rb +5 -5
 - data/examples/shape5.rb +6 -6
 - data/examples/shape6.rb +6 -6
 - data/examples/shape7.rb +11 -11
 - data/examples/shape8.rb +10 -10
 - data/examples/shape_all.rb +0 -0
 - data/examples/vbaProject.bin +0 -0
 - data/lib/write_xlsx/chart.rb +656 -56
 - data/lib/write_xlsx/chartsheet.rb +26 -2
 - data/lib/write_xlsx/format.rb +50 -27
 - data/lib/write_xlsx/formats.rb +32 -0
 - data/lib/write_xlsx/package/packager.rb +45 -238
 - data/lib/write_xlsx/package/table.rb +9 -18
 - data/lib/write_xlsx/package/xml_writer_simple.rb +26 -9
 - data/lib/write_xlsx/sheets.rb +223 -0
 - data/lib/write_xlsx/sparkline.rb +140 -4
 - data/lib/write_xlsx/version.rb +1 -1
 - data/lib/write_xlsx/workbook.rb +34 -121
 - data/lib/write_xlsx/worksheet/data_validation.rb +291 -0
 - data/lib/write_xlsx/worksheet/hyperlink.rb +111 -0
 - data/lib/write_xlsx/worksheet/page_setup.rb +170 -0
 - data/lib/write_xlsx/worksheet.rb +1112 -1334
 - data/test/helper.rb +1 -1
 - data/test/package/styles/test_styles_01.rb +1 -10
 - data/test/package/styles/test_styles_02.rb +1 -10
 - data/test/package/styles/test_styles_03.rb +1 -10
 - data/test/package/styles/test_styles_04.rb +1 -10
 - data/test/package/styles/test_styles_05.rb +1 -10
 - data/test/package/styles/test_styles_06.rb +1 -10
 - data/test/package/styles/test_styles_07.rb +1 -10
 - data/test/package/styles/test_styles_08.rb +1 -10
 - data/test/package/styles/test_styles_09.rb +1 -10
 - data/test/perl_output/conditional_format.xlsx +0 -0
 - data/test/perl_output/outline_collapsed.xlsx +0 -0
 - data/test/perl_output/protection.xlsx +0 -0
 - data/test/regression/test_chart_gap01.rb +47 -0
 - data/test/regression/test_chart_gap02.rb +47 -0
 - data/test/regression/test_chart_gap03.rb +47 -0
 - data/test/regression/test_format05.rb +26 -0
 - data/test/regression/test_rich_string12.rb +32 -0
 - data/test/regression/xlsx_files/chart_gap01.xlsx +0 -0
 - data/test/regression/xlsx_files/chart_gap02.xlsx +0 -0
 - data/test/regression/xlsx_files/chart_gap03.xlsx +0 -0
 - data/test/regression/xlsx_files/format05.xlsx +0 -0
 - data/test/regression/xlsx_files/rich_string12.xlsx +0 -0
 - data/test/test_example_match.rb +253 -20
 - data/test/worksheet/test_set_column.rb +25 -0
 - data/test/worksheet/test_worksheet_03.rb +1 -1
 - data/test/worksheet/test_worksheet_04.rb +1 -1
 - data/test/worksheet/test_write_array_formula_01.rb +7 -0
 - data/test/worksheet/test_write_col_breaks.rb +2 -2
 - data/test/worksheet/test_write_col_info.rb +8 -8
 - data/test/worksheet/test_write_conditional_formatting.rb +4 -4
 - data/test/worksheet/test_write_formula_does_not_change_formula_string.rb +18 -0
 - data/test/worksheet/test_write_header_footer.rb +8 -3
 - data/test/worksheet/test_write_hyperlink.rb +10 -5
 - data/test/worksheet/test_write_merge_cells.rb +6 -6
 - data/test/worksheet/test_write_page_set_up_pr.rb +1 -1
 - data/test/worksheet/test_write_page_setup.rb +1 -1
 - data/test/worksheet/test_write_row_breaks.rb +2 -2
 - data/test/worksheet/test_write_row_element.rb +1 -1
 - data/test/worksheet/test_write_sheet_pr.rb +2 -2
 - data/test/worksheet/test_write_sheet_view.rb +0 -9
 - data/test/worksheet/test_write_url.rb +19 -0
 - data/test/worksheet/test_write_worksheet_attributes.rb +21 -0
 - metadata +38 -5
 - data/lib/write_xlsx/worksheet/print_style.rb +0 -51
 - data/test/worksheet/test_write_worksheet.rb +0 -19
 
    
        data/lib/write_xlsx/workbook.rb
    CHANGED
    
    | 
         @@ -1,8 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # -*- coding: utf-8 -*-
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'write_xlsx/package/xml_writer_simple'
         
     | 
| 
       3 
3 
     | 
    
         
             
            require 'write_xlsx/package/packager'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'write_xlsx/sheets'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require 'write_xlsx/worksheet'
         
     | 
| 
       5 
6 
     | 
    
         
             
            require 'write_xlsx/chartsheet'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'write_xlsx/formats'
         
     | 
| 
       6 
8 
     | 
    
         
             
            require 'write_xlsx/format'
         
     | 
| 
       7 
9 
     | 
    
         
             
            require 'write_xlsx/shape'
         
     | 
| 
       8 
10 
     | 
    
         
             
            require 'write_xlsx/utility'
         
     | 
| 
         @@ -14,6 +16,8 @@ require 'digest/md5' 
     | 
|
| 
       14 
16 
     | 
    
         | 
| 
       15 
17 
     | 
    
         
             
            module Writexlsx
         
     | 
| 
       16 
18 
     | 
    
         | 
| 
      
 19 
     | 
    
         
            +
              OFFICE_URL = 'http://schemas.microsoft.com/office/'   # :nodoc:
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       17 
21 
     | 
    
         
             
              # The WriteXLSX provides an object oriented interface to a new Excel workbook.
         
     | 
| 
       18 
22 
     | 
    
         
             
              # The following methods are available through a new workbook.
         
     | 
| 
       19 
23 
     | 
    
         
             
              #
         
     | 
| 
         @@ -34,12 +38,9 @@ module Writexlsx 
     | 
|
| 
       34 
38 
     | 
    
         | 
| 
       35 
39 
     | 
    
         
             
                include Writexlsx::Utility
         
     | 
| 
       36 
40 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
                BASE_NAME = { :sheet => 'Sheet', :chart => 'Chart'}  # :nodoc:
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
41 
     | 
    
         
             
                attr_writer :firstsheet  # :nodoc:
         
     | 
| 
       40 
42 
     | 
    
         
             
                attr_reader :palette  # :nodoc:
         
     | 
| 
       41 
     | 
    
         
            -
                attr_reader : 
     | 
| 
       42 
     | 
    
         
            -
                attr_reader :worksheets, :sheetnames, :charts, :drawings  # :nodoc:
         
     | 
| 
      
 43 
     | 
    
         
            +
                attr_reader :worksheets, :charts, :drawings  # :nodoc:
         
     | 
| 
       43 
44 
     | 
    
         
             
                attr_reader :num_comment_files, :num_vml_files, :named_ranges  # :nodoc:
         
     | 
| 
       44 
45 
     | 
    
         
             
                attr_reader :doc_properties  # :nodoc:
         
     | 
| 
       45 
46 
     | 
    
         
             
                attr_reader :image_types, :images  # :nodoc:
         
     | 
| 
         @@ -97,19 +98,12 @@ module Writexlsx 
     | 
|
| 
       97 
98 
     | 
    
         
             
                  @firstsheet          = 0
         
     | 
| 
       98 
99 
     | 
    
         
             
                  @selected            = 0
         
     | 
| 
       99 
100 
     | 
    
         
             
                  @fileclosed          = false
         
     | 
| 
       100 
     | 
    
         
            -
                  @ 
     | 
| 
       101 
     | 
    
         
            -
                  @chart_name          = 'Chart'
         
     | 
| 
       102 
     | 
    
         
            -
                  @sheetname_count     = 0
         
     | 
| 
       103 
     | 
    
         
            -
                  @chartname_count     = 0
         
     | 
| 
       104 
     | 
    
         
            -
                  @worksheets          = []
         
     | 
| 
      
 101 
     | 
    
         
            +
                  @worksheets          = Sheets.new
         
     | 
| 
       105 
102 
     | 
    
         
             
                  @charts              = []
         
     | 
| 
       106 
103 
     | 
    
         
             
                  @drawings            = []
         
     | 
| 
       107 
     | 
    
         
            -
                  @ 
     | 
| 
       108 
     | 
    
         
            -
                  @formats             = []
         
     | 
| 
      
 104 
     | 
    
         
            +
                  @formats             = Formats.new
         
     | 
| 
       109 
105 
     | 
    
         
             
                  @xf_formats          = []
         
     | 
| 
       110 
     | 
    
         
            -
                  @xf_format_indices   = {}
         
     | 
| 
       111 
106 
     | 
    
         
             
                  @dxf_formats         = []
         
     | 
| 
       112 
     | 
    
         
            -
                  @dxf_format_indices  = {}
         
     | 
| 
       113 
107 
     | 
    
         
             
                  @font_count          = 0
         
     | 
| 
       114 
108 
     | 
    
         
             
                  @num_format_count    = 0
         
     | 
| 
       115 
109 
     | 
    
         
             
                  @defined_names       = []
         
     | 
| 
         @@ -265,7 +259,7 @@ module Writexlsx 
     | 
|
| 
       265 
259 
     | 
    
         
             
                  write_book_views
         
     | 
| 
       266 
260 
     | 
    
         | 
| 
       267 
261 
     | 
    
         
             
                  # Write the worksheet names and ids.
         
     | 
| 
       268 
     | 
    
         
            -
                  write_sheets
         
     | 
| 
      
 262 
     | 
    
         
            +
                  @worksheets.write_sheets(@writer)
         
     | 
| 
       269 
263 
     | 
    
         | 
| 
       270 
264 
     | 
    
         
             
                  # Write the workbook defined names.
         
     | 
| 
       271 
265 
     | 
    
         
             
                  write_defined_names
         
     | 
| 
         @@ -305,7 +299,6 @@ module Writexlsx 
     | 
|
| 
       305 
299 
     | 
    
         
             
                  name  = check_sheetname(name)
         
     | 
| 
       306 
300 
     | 
    
         
             
                  worksheet = Worksheet.new(self, @worksheets.size, name)
         
     | 
| 
       307 
301 
     | 
    
         
             
                  @worksheets << worksheet
         
     | 
| 
       308 
     | 
    
         
            -
                  @sheetnames << name
         
     | 
| 
       309 
302 
     | 
    
         
             
                  worksheet
         
     | 
| 
       310 
303 
     | 
    
         
             
                end
         
     | 
| 
       311 
304 
     | 
    
         | 
| 
         @@ -403,7 +396,6 @@ module Writexlsx 
     | 
|
| 
       403 
396 
     | 
    
         
             
                    chartsheet = Chartsheet.new(self, @worksheets.size, sheetname)
         
     | 
| 
       404 
397 
     | 
    
         
             
                    chartsheet.chart   = chart
         
     | 
| 
       405 
398 
     | 
    
         
             
                    @worksheets << chartsheet
         
     | 
| 
       406 
     | 
    
         
            -
                    @sheetnames << sheetname
         
     | 
| 
       407 
399 
     | 
    
         
             
                  end
         
     | 
| 
       408 
400 
     | 
    
         
             
                  @charts << chart
         
     | 
| 
       409 
401 
     | 
    
         
             
                  ptrue?(embedded) ? chart : chartsheet
         
     | 
| 
         @@ -422,15 +414,9 @@ module Writexlsx 
     | 
|
| 
       422 
414 
     | 
    
         
             
                # Format properties and how to set them.
         
     | 
| 
       423 
415 
     | 
    
         
             
                #
         
     | 
| 
       424 
416 
     | 
    
         
             
                def add_format(properties = {})
         
     | 
| 
       425 
     | 
    
         
            -
                   
     | 
| 
       426 
     | 
    
         
            -
                    @xf_format_indices,
         
     | 
| 
       427 
     | 
    
         
            -
                    @dxf_format_indices,
         
     | 
| 
       428 
     | 
    
         
            -
                    properties
         
     | 
| 
       429 
     | 
    
         
            -
                  ]
         
     | 
| 
      
 417 
     | 
    
         
            +
                  format = Format.new(@formats, properties)
         
     | 
| 
       430 
418 
     | 
    
         | 
| 
       431 
     | 
    
         
            -
                  format  
     | 
| 
       432 
     | 
    
         
            -
             
     | 
| 
       433 
     | 
    
         
            -
                  @formats.push(format)    # Store format reference
         
     | 
| 
      
 419 
     | 
    
         
            +
                  @formats.formats.push(format)    # Store format reference
         
     | 
| 
       434 
420 
     | 
    
         | 
| 
       435 
421 
     | 
    
         
             
                  format
         
     | 
| 
       436 
422 
     | 
    
         
             
                end
         
     | 
| 
         @@ -716,7 +702,7 @@ module Writexlsx 
     | 
|
| 
       716 
702 
     | 
    
         
             
                  if name =~ /^(.*)!(.*)$/
         
     | 
| 
       717 
703 
     | 
    
         
             
                    sheetname   = $1
         
     | 
| 
       718 
704 
     | 
    
         
             
                    name        = $2
         
     | 
| 
       719 
     | 
    
         
            -
                    sheet_index =  
     | 
| 
      
 705 
     | 
    
         
            +
                    sheet_index = @worksheets.index_by_name(sheetname)
         
     | 
| 
       720 
706 
     | 
    
         
             
                  else
         
     | 
| 
       721 
707 
     | 
    
         
             
                    sheet_index = -1   # Use -1 to indicate global names.
         
     | 
| 
       722 
708 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -946,12 +932,21 @@ module Writexlsx 
     | 
|
| 
       946 
932 
     | 
    
         
             
                  @shared_strings.empty?
         
     | 
| 
       947 
933 
     | 
    
         
             
                end
         
     | 
| 
       948 
934 
     | 
    
         | 
| 
       949 
     | 
    
         
            -
                def  
     | 
| 
       950 
     | 
    
         
            -
                  @ 
     | 
| 
      
 935 
     | 
    
         
            +
                def chartsheet_count
         
     | 
| 
      
 936 
     | 
    
         
            +
                  @worksheets.chartsheet_count
         
     | 
| 
       951 
937 
     | 
    
         
             
                end
         
     | 
| 
       952 
938 
     | 
    
         | 
| 
       953 
     | 
    
         
            -
                def  
     | 
| 
       954 
     | 
    
         
            -
                   
     | 
| 
      
 939 
     | 
    
         
            +
                def style_properties
         
     | 
| 
      
 940 
     | 
    
         
            +
                  [
         
     | 
| 
      
 941 
     | 
    
         
            +
                   @xf_formats,
         
     | 
| 
      
 942 
     | 
    
         
            +
                   @palette,
         
     | 
| 
      
 943 
     | 
    
         
            +
                   @font_count,
         
     | 
| 
      
 944 
     | 
    
         
            +
                   @num_format_count,
         
     | 
| 
      
 945 
     | 
    
         
            +
                   @border_count,
         
     | 
| 
      
 946 
     | 
    
         
            +
                   @fill_count,
         
     | 
| 
      
 947 
     | 
    
         
            +
                   @custom_colors,
         
     | 
| 
      
 948 
     | 
    
         
            +
                   @dxf_formats
         
     | 
| 
      
 949 
     | 
    
         
            +
                  ]
         
     | 
| 
       955 
950 
     | 
    
         
             
                end
         
     | 
| 
       956 
951 
     | 
    
         | 
| 
       957 
952 
     | 
    
         
             
                private
         
     | 
| 
         @@ -1037,52 +1032,11 @@ module Writexlsx 
     | 
|
| 
       1037 
1032 
     | 
    
         
             
                # invalid characters and if the name is unique in the workbook.
         
     | 
| 
       1038 
1033 
     | 
    
         
             
                #
         
     | 
| 
       1039 
1034 
     | 
    
         
             
                def check_sheetname(name) #:nodoc:
         
     | 
| 
       1040 
     | 
    
         
            -
                  make_and_check_sheet_chart_name(:sheet, name)
         
     | 
| 
      
 1035 
     | 
    
         
            +
                  @worksheets.make_and_check_sheet_chart_name(:sheet, name)
         
     | 
| 
       1041 
1036 
     | 
    
         
             
                end
         
     | 
| 
       1042 
1037 
     | 
    
         | 
| 
       1043 
1038 
     | 
    
         
             
                def check_chart_sheetname(name)
         
     | 
| 
       1044 
     | 
    
         
            -
                  make_and_check_sheet_chart_name(:chart, name)
         
     | 
| 
       1045 
     | 
    
         
            -
                end
         
     | 
| 
       1046 
     | 
    
         
            -
             
     | 
| 
       1047 
     | 
    
         
            -
                def make_and_check_sheet_chart_name(type, name)
         
     | 
| 
       1048 
     | 
    
         
            -
                  count = sheet_chart_count_increment(type)
         
     | 
| 
       1049 
     | 
    
         
            -
                  name = "#{BASE_NAME[type]}#{count}" unless ptrue?(name)
         
     | 
| 
       1050 
     | 
    
         
            -
             
     | 
| 
       1051 
     | 
    
         
            -
                  check_valid_sheetname(name)
         
     | 
| 
       1052 
     | 
    
         
            -
                  name
         
     | 
| 
       1053 
     | 
    
         
            -
                end
         
     | 
| 
       1054 
     | 
    
         
            -
             
     | 
| 
       1055 
     | 
    
         
            -
                def sheet_chart_count_increment(type)
         
     | 
| 
       1056 
     | 
    
         
            -
                  case type
         
     | 
| 
       1057 
     | 
    
         
            -
                  when :sheet
         
     | 
| 
       1058 
     | 
    
         
            -
                    @sheetname_count += 1
         
     | 
| 
       1059 
     | 
    
         
            -
                  when :chart
         
     | 
| 
       1060 
     | 
    
         
            -
                    @chartname_count += 1
         
     | 
| 
       1061 
     | 
    
         
            -
                  end
         
     | 
| 
       1062 
     | 
    
         
            -
                end
         
     | 
| 
       1063 
     | 
    
         
            -
             
     | 
| 
       1064 
     | 
    
         
            -
                def check_valid_sheetname(name)
         
     | 
| 
       1065 
     | 
    
         
            -
                  # Check that sheet name is <= 31. Excel limit.
         
     | 
| 
       1066 
     | 
    
         
            -
                  raise "Sheetname #{name} must be <= #{SHEETNAME_MAX} chars" if name.length > SHEETNAME_MAX
         
     | 
| 
       1067 
     | 
    
         
            -
             
     | 
| 
       1068 
     | 
    
         
            -
                  # Check that sheetname doesn't contain any invalid characters
         
     | 
| 
       1069 
     | 
    
         
            -
                  invalid_char = /[\[\]:*?\/\\]/
         
     | 
| 
       1070 
     | 
    
         
            -
                  if name =~ invalid_char
         
     | 
| 
       1071 
     | 
    
         
            -
                    raise 'Invalid character []:*?/\\ in worksheet name: ' + name
         
     | 
| 
       1072 
     | 
    
         
            -
                  end
         
     | 
| 
       1073 
     | 
    
         
            -
             
     | 
| 
       1074 
     | 
    
         
            -
                  # Check that the worksheet name doesn't already exist since this is a fatal
         
     | 
| 
       1075 
     | 
    
         
            -
                  # error in Excel 97. The check must also exclude case insensitive matches.
         
     | 
| 
       1076 
     | 
    
         
            -
                  unless is_sheetname_uniq?(name)
         
     | 
| 
       1077 
     | 
    
         
            -
                    raise "Worksheet name '#{name}', with case ignored, is already used."
         
     | 
| 
       1078 
     | 
    
         
            -
                  end
         
     | 
| 
       1079 
     | 
    
         
            -
                end
         
     | 
| 
       1080 
     | 
    
         
            -
             
     | 
| 
       1081 
     | 
    
         
            -
                def is_sheetname_uniq?(name)
         
     | 
| 
       1082 
     | 
    
         
            -
                  @worksheets.each do |worksheet|
         
     | 
| 
       1083 
     | 
    
         
            -
                    return false if name.downcase == worksheet.name.downcase
         
     | 
| 
       1084 
     | 
    
         
            -
                  end
         
     | 
| 
       1085 
     | 
    
         
            -
                  true
         
     | 
| 
      
 1039 
     | 
    
         
            +
                  @worksheets.make_and_check_sheet_chart_name(:chart, name)
         
     | 
| 
       1086 
1040 
     | 
    
         
             
                end
         
     | 
| 
       1087 
1041 
     | 
    
         | 
| 
       1088 
1042 
     | 
    
         
             
                #
         
     | 
| 
         @@ -1184,29 +1138,6 @@ module Writexlsx 
     | 
|
| 
       1184 
1138 
     | 
    
         
             
                  @writer.empty_tag('workbookView', attributes)
         
     | 
| 
       1185 
1139 
     | 
    
         
             
                end
         
     | 
| 
       1186 
1140 
     | 
    
         | 
| 
       1187 
     | 
    
         
            -
                def write_sheets #:nodoc:
         
     | 
| 
       1188 
     | 
    
         
            -
                  @writer.tag_elements('sheets') do
         
     | 
| 
       1189 
     | 
    
         
            -
                    id_num = 1
         
     | 
| 
       1190 
     | 
    
         
            -
                    @worksheets.each do |sheet|
         
     | 
| 
       1191 
     | 
    
         
            -
                      write_sheet(sheet.name, id_num, sheet.hidden?)
         
     | 
| 
       1192 
     | 
    
         
            -
                      id_num += 1
         
     | 
| 
       1193 
     | 
    
         
            -
                    end
         
     | 
| 
       1194 
     | 
    
         
            -
                  end
         
     | 
| 
       1195 
     | 
    
         
            -
                end
         
     | 
| 
       1196 
     | 
    
         
            -
             
     | 
| 
       1197 
     | 
    
         
            -
                def write_sheet(name, sheet_id, hidden = false) #:nodoc:
         
     | 
| 
       1198 
     | 
    
         
            -
                  attributes = [
         
     | 
| 
       1199 
     | 
    
         
            -
                    'name',    name,
         
     | 
| 
       1200 
     | 
    
         
            -
                    'sheetId', sheet_id
         
     | 
| 
       1201 
     | 
    
         
            -
                  ]
         
     | 
| 
       1202 
     | 
    
         
            -
             
     | 
| 
       1203 
     | 
    
         
            -
                  if hidden
         
     | 
| 
       1204 
     | 
    
         
            -
                    attributes << 'state' << 'hidden'
         
     | 
| 
       1205 
     | 
    
         
            -
                  end
         
     | 
| 
       1206 
     | 
    
         
            -
                  attributes << 'r:id' << "rId#{sheet_id}"
         
     | 
| 
       1207 
     | 
    
         
            -
                  @writer.empty_tag_encoded('sheet', attributes)
         
     | 
| 
       1208 
     | 
    
         
            -
                end
         
     | 
| 
       1209 
     | 
    
         
            -
             
     | 
| 
       1210 
1141 
     | 
    
         
             
                def write_calc_pr #:nodoc:
         
     | 
| 
       1211 
1142 
     | 
    
         
             
                  attributes = ['calcId', 124519]
         
     | 
| 
       1212 
1143 
     | 
    
         
             
                  @writer.empty_tag('calcPr', attributes)
         
     | 
| 
         @@ -1219,9 +1150,10 @@ module Writexlsx 
     | 
|
| 
       1219 
1150 
     | 
    
         | 
| 
       1220 
1151 
     | 
    
         
             
                def write_ext #:nodoc:
         
     | 
| 
       1221 
1152 
     | 
    
         
             
                  tag = 'ext'
         
     | 
| 
      
 1153 
     | 
    
         
            +
                  uri = "#{OFFICE_URL}mac/excel/2008/main"
         
     | 
| 
       1222 
1154 
     | 
    
         
             
                  attributes = [
         
     | 
| 
       1223 
     | 
    
         
            -
                    'xmlns:mx',  
     | 
| 
       1224 
     | 
    
         
            -
                    'uri',  
     | 
| 
      
 1155 
     | 
    
         
            +
                    'xmlns:mx', uri,
         
     | 
| 
      
 1156 
     | 
    
         
            +
                    'uri', uri
         
     | 
| 
       1225 
1157 
     | 
    
         
             
                  ]
         
     | 
| 
       1226 
1158 
     | 
    
         
             
                  @writer.tag_elements(tag, attributes) { write_mx_arch_id }
         
     | 
| 
       1227 
1159 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1289,8 +1221,7 @@ module Writexlsx 
     | 
|
| 
       1289 
1221 
     | 
    
         
             
                  add_chart_data
         
     | 
| 
       1290 
1222 
     | 
    
         | 
| 
       1291 
1223 
     | 
    
         
             
                  # Package the workbook.
         
     | 
| 
       1292 
     | 
    
         
            -
                  packager = Package::Packager.new
         
     | 
| 
       1293 
     | 
    
         
            -
                  packager.add_workbook(self)
         
     | 
| 
      
 1224 
     | 
    
         
            +
                  packager = Package::Packager.new(self)
         
     | 
| 
       1294 
1225 
     | 
    
         
             
                  packager.set_package_dir(@tempdir)
         
     | 
| 
       1295 
1226 
     | 
    
         
             
                  packager.create_package
         
     | 
| 
       1296 
1227 
     | 
    
         | 
| 
         @@ -1328,7 +1259,7 @@ module Writexlsx 
     | 
|
| 
       1328 
1259 
     | 
    
         
             
                # formats.
         
     | 
| 
       1329 
1260 
     | 
    
         
             
                #
         
     | 
| 
       1330 
1261 
     | 
    
         
             
                def prepare_formats #:nodoc:
         
     | 
| 
       1331 
     | 
    
         
            -
                  @formats.each do |format|
         
     | 
| 
      
 1262 
     | 
    
         
            +
                  @formats.formats.each do |format|
         
     | 
| 
       1332 
1263 
     | 
    
         
             
                    xf_index  = format.xf_index
         
     | 
| 
       1333 
1264 
     | 
    
         
             
                    dxf_index = format.dxf_index
         
     | 
| 
       1334 
1265 
     | 
    
         | 
| 
         @@ -1562,8 +1493,7 @@ module Writexlsx 
     | 
|
| 
       1562 
1493 
     | 
    
         
             
                  # Add a font format for cell comments.
         
     | 
| 
       1563 
1494 
     | 
    
         
             
                  if comment_files > 0
         
     | 
| 
       1564 
1495 
     | 
    
         
             
                    format = Format.new(
         
     | 
| 
       1565 
     | 
    
         
            -
                        @ 
     | 
| 
       1566 
     | 
    
         
            -
                        @dxf_format_indices,
         
     | 
| 
      
 1496 
     | 
    
         
            +
                        @formats,
         
     | 
| 
       1567 
1497 
     | 
    
         
             
                        :font          => 'Tahoma',
         
     | 
| 
       1568 
1498 
     | 
    
         
             
                        :size          => 8,
         
     | 
| 
       1569 
1499 
     | 
    
         
             
                        :color_indexed => 81,
         
     | 
| 
         @@ -1572,7 +1502,7 @@ module Writexlsx 
     | 
|
| 
       1572 
1502 
     | 
    
         | 
| 
       1573 
1503 
     | 
    
         
             
                    format.get_xf_index
         
     | 
| 
       1574 
1504 
     | 
    
         | 
| 
       1575 
     | 
    
         
            -
                    @formats << format
         
     | 
| 
      
 1505 
     | 
    
         
            +
                    @formats.formats << format
         
     | 
| 
       1576 
1506 
     | 
    
         
             
                  end
         
     | 
| 
       1577 
1507 
     | 
    
         
             
                end
         
     | 
| 
       1578 
1508 
     | 
    
         | 
| 
         @@ -1728,7 +1658,7 @@ module Writexlsx 
     | 
|
| 
       1728 
1658 
     | 
    
         | 
| 
       1729 
1659 
     | 
    
         
             
                    drawing_id += 1
         
     | 
| 
       1730 
1660 
     | 
    
         | 
| 
       1731 
     | 
    
         
            -
                     
     | 
| 
      
 1661 
     | 
    
         
            +
                    sheet.charts.each_with_index do |chart, index|
         
     | 
| 
       1732 
1662 
     | 
    
         
             
                      chart_ref_id += 1
         
     | 
| 
       1733 
1663 
     | 
    
         
             
                      sheet.prepare_chart(index, chart_ref_id, drawing_id)
         
     | 
| 
       1734 
1664 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -1758,23 +1688,6 @@ module Writexlsx 
     | 
|
| 
       1758 
1688 
     | 
    
         
             
                  @drawing_count = drawing_id
         
     | 
| 
       1759 
1689 
     | 
    
         
             
                end
         
     | 
| 
       1760 
1690 
     | 
    
         | 
| 
       1761 
     | 
    
         
            -
                #
         
     | 
| 
       1762 
     | 
    
         
            -
                # Convert a sheet name to its index. Return undef otherwise.
         
     | 
| 
       1763 
     | 
    
         
            -
                #
         
     | 
| 
       1764 
     | 
    
         
            -
                def get_sheet_index(sheetname) #:nodoc:
         
     | 
| 
       1765 
     | 
    
         
            -
                  sheet_count = @sheetnames.size
         
     | 
| 
       1766 
     | 
    
         
            -
                  sheet_index = nil
         
     | 
| 
       1767 
     | 
    
         
            -
             
     | 
| 
       1768 
     | 
    
         
            -
                  sheetname.sub!(/^'/, '')
         
     | 
| 
       1769 
     | 
    
         
            -
                  sheetname.sub!(/'$/, '')
         
     | 
| 
       1770 
     | 
    
         
            -
             
     | 
| 
       1771 
     | 
    
         
            -
                  ( 0 .. sheet_count - 1 ).each do |i|
         
     | 
| 
       1772 
     | 
    
         
            -
                    sheet_index = i if sheetname == @sheetnames[i]
         
     | 
| 
       1773 
     | 
    
         
            -
                  end
         
     | 
| 
       1774 
     | 
    
         
            -
             
     | 
| 
       1775 
     | 
    
         
            -
                  sheet_index
         
     | 
| 
       1776 
     | 
    
         
            -
                end
         
     | 
| 
       1777 
     | 
    
         
            -
             
     | 
| 
       1778 
1691 
     | 
    
         
             
                #
         
     | 
| 
       1779 
1692 
     | 
    
         
             
                # Extract information from the image file such as dimension, type, filename,
         
     | 
| 
       1780 
1693 
     | 
    
         
             
                # and extension. Also keep track of previously seen images to optimise out
         
     | 
| 
         @@ -0,0 +1,291 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Writexlsx
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Worksheet
         
     | 
| 
      
 5 
     | 
    
         
            +
                class DataValidation   # :nodoc:
         
     | 
| 
      
 6 
     | 
    
         
            +
                  include Writexlsx::Utility
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :value, :source, :minimum, :maximum, :validate, :criteria
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :error_type, :cells, :other_cells
         
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :ignore_blank, :dropdown, :show_input, :show_error
         
     | 
| 
      
 11 
     | 
    
         
            +
                  attr_reader :error_title, :error_message, :input_title, :input_message
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(*args)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    # Check for a cell reference in A1 notation and substitute row and column.
         
     | 
| 
      
 15 
     | 
    
         
            +
                    row1, col1, row2, col2, options = row_col_notation(args)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    if row2.respond_to?(:keys)
         
     | 
| 
      
 17 
     | 
    
         
            +
                      options_to_instance_variable(row2.dup)
         
     | 
| 
      
 18 
     | 
    
         
            +
                      row2, col2 = row1, col1
         
     | 
| 
      
 19 
     | 
    
         
            +
                    elsif options.respond_to?(:keys)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      options_to_instance_variable(options.dup)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    else
         
     | 
| 
      
 22 
     | 
    
         
            +
                      raise WriteXLSXInsufficientArgumentError
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    raise WriteXLSXInsufficientArgumentError if [row1, col1, row2, col2].include?(nil)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    check_for_valid_input_params
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    check_dimensions(row1, col1)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    check_dimensions(row2, col2)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @cells = [[row1, col1, row2, col2]]
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    @value = @source  if @source
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @value = @minimum if @minimum
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    @validate = valid_validation_type[@validate.downcase]
         
     | 
| 
      
 35 
     | 
    
         
            +
                    if @validate == 'none'
         
     | 
| 
      
 36 
     | 
    
         
            +
                      @validate_none = true
         
     | 
| 
      
 37 
     | 
    
         
            +
                      return
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
                    if ['list', 'custom'].include?(@validate)
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @criteria  = 'between'
         
     | 
| 
      
 41 
     | 
    
         
            +
                      @maximum   = nil
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    check_criteria_required
         
     | 
| 
      
 45 
     | 
    
         
            +
                    check_valid_citeria_types
         
     | 
| 
      
 46 
     | 
    
         
            +
                    @criteria = valid_criteria_type[@criteria.downcase]
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                    check_maximum_value_when_criteria_is_between_or_notbetween
         
     | 
| 
      
 49 
     | 
    
         
            +
                    @error_type = has_key?(:error_type) ? error_type_hash[@error_type.downcase] : 0
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    convert_date_time_value_if_required
         
     | 
| 
      
 52 
     | 
    
         
            +
                    set_some_defaults
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  # A (for now) undocumented parameter to pass additional cell ranges.
         
     | 
| 
      
 55 
     | 
    
         
            +
                    @other_cells.each { |cells| @cells << cells } if has_key?(:other_cells)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  def options_to_instance_variable(params)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    params.each do |k, v|
         
     | 
| 
      
 60 
     | 
    
         
            +
                      instance_variable_set("@#{k}", v)
         
     | 
| 
      
 61 
     | 
    
         
            +
                    end
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  def keys
         
     | 
| 
      
 65 
     | 
    
         
            +
                    self.instance_variables.collect { |v| v.to_s.sub(/@/, '').to_sym }
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  def validate_none?
         
     | 
| 
      
 69 
     | 
    
         
            +
                    @validate_none
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                  #
         
     | 
| 
      
 73 
     | 
    
         
            +
                  # Write the <dataValidation> element.
         
     | 
| 
      
 74 
     | 
    
         
            +
                  #
         
     | 
| 
      
 75 
     | 
    
         
            +
                  def write_data_validation(writer) #:nodoc:
         
     | 
| 
      
 76 
     | 
    
         
            +
                    @writer = writer
         
     | 
| 
      
 77 
     | 
    
         
            +
                    @writer.tag_elements('dataValidation', attributes) do
         
     | 
| 
      
 78 
     | 
    
         
            +
                      # Write the formula1 element.
         
     | 
| 
      
 79 
     | 
    
         
            +
                      write_formula_1(@value)
         
     | 
| 
      
 80 
     | 
    
         
            +
                      # Write the formula2 element.
         
     | 
| 
      
 81 
     | 
    
         
            +
                      write_formula_2(@maximum) if @maximum
         
     | 
| 
      
 82 
     | 
    
         
            +
                    end
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  private
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  #
         
     | 
| 
      
 88 
     | 
    
         
            +
                  # Write the <formula1> element.
         
     | 
| 
      
 89 
     | 
    
         
            +
                  #
         
     | 
| 
      
 90 
     | 
    
         
            +
                  def write_formula_1(formula) #:nodoc:
         
     | 
| 
      
 91 
     | 
    
         
            +
                    # Convert a list array ref into a comma separated string.
         
     | 
| 
      
 92 
     | 
    
         
            +
                    formula   = %!"#{formula.join(',')}"! if formula.kind_of?(Array)
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                    formula = formula.sub(/^=/, '') if formula.respond_to?(:sub)
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                    @writer.data_element('formula1', formula)
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  #
         
     | 
| 
      
 100 
     | 
    
         
            +
                  # Write the <formula2> element.
         
     | 
| 
      
 101 
     | 
    
         
            +
                  #
         
     | 
| 
      
 102 
     | 
    
         
            +
                  def write_formula_2(formula) #:nodoc:
         
     | 
| 
      
 103 
     | 
    
         
            +
                    formula = formula.sub(/^=/, '') if formula.respond_to?(:sub)
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    @writer.data_element('formula2', formula)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                  def attributes
         
     | 
| 
      
 109 
     | 
    
         
            +
                    sqref      = ''
         
     | 
| 
      
 110 
     | 
    
         
            +
                    attributes = []
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                    # Set the cell range(s) for the data validation.
         
     | 
| 
      
 113 
     | 
    
         
            +
                    @cells.each do |cells|
         
     | 
| 
      
 114 
     | 
    
         
            +
                      # Add a space between multiple cell ranges.
         
     | 
| 
      
 115 
     | 
    
         
            +
                      sqref += ' ' if sqref != ''
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                      row_first, col_first, row_last, col_last = cells
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                      # Swap last row/col for first row/col as necessary
         
     | 
| 
      
 120 
     | 
    
         
            +
                      row_first, row_last = row_last, row_first if row_first > row_last
         
     | 
| 
      
 121 
     | 
    
         
            +
                      col_first, col_last = col_last, col_first if col_first > col_last
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                      # If the first and last cell are the same write a single cell.
         
     | 
| 
      
 124 
     | 
    
         
            +
                      if row_first == row_last && col_first == col_last
         
     | 
| 
      
 125 
     | 
    
         
            +
                        sqref += xl_rowcol_to_cell(row_first, col_first)
         
     | 
| 
      
 126 
     | 
    
         
            +
                      else
         
     | 
| 
      
 127 
     | 
    
         
            +
                        sqref += xl_range(row_first, row_last, col_first, col_last)
         
     | 
| 
      
 128 
     | 
    
         
            +
                      end
         
     | 
| 
      
 129 
     | 
    
         
            +
                    end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                    attributes << 'type' << @validate
         
     | 
| 
      
 132 
     | 
    
         
            +
                    attributes << 'operator' << @criteria if @criteria != 'between'
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                    if @error_type
         
     | 
| 
      
 135 
     | 
    
         
            +
                      attributes << 'errorStyle' << 'warning' if @error_type == 1
         
     | 
| 
      
 136 
     | 
    
         
            +
                      attributes << 'errorStyle' << 'information' if @error_type == 2
         
     | 
| 
      
 137 
     | 
    
         
            +
                    end
         
     | 
| 
      
 138 
     | 
    
         
            +
                    attributes << 'allowBlank'       << 1 if @ignore_blank != 0
         
     | 
| 
      
 139 
     | 
    
         
            +
                    attributes << 'showDropDown'     << 1 if @dropdown     == 0
         
     | 
| 
      
 140 
     | 
    
         
            +
                    attributes << 'showInputMessage' << 1 if @show_input   != 0
         
     | 
| 
      
 141 
     | 
    
         
            +
                    attributes << 'showErrorMessage' << 1 if @show_error   != 0
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                    attributes << 'errorTitle'  << @error_title   if @error_title
         
     | 
| 
      
 144 
     | 
    
         
            +
                    attributes << 'error'       << @error_message if @error_message
         
     | 
| 
      
 145 
     | 
    
         
            +
                    attributes << 'promptTitle' << @input_title   if @input_title
         
     | 
| 
      
 146 
     | 
    
         
            +
                    attributes << 'prompt'      << @input_message if @input_message
         
     | 
| 
      
 147 
     | 
    
         
            +
                    attributes << 'sqref'       << sqref
         
     | 
| 
      
 148 
     | 
    
         
            +
                  end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  def has_key?(key)
         
     | 
| 
      
 151 
     | 
    
         
            +
                    keys.index(key)
         
     | 
| 
      
 152 
     | 
    
         
            +
                  end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
                  def set_some_defaults
         
     | 
| 
      
 155 
     | 
    
         
            +
                    @ignore_blank ||= 1
         
     | 
| 
      
 156 
     | 
    
         
            +
                    @dropdown     ||= 1
         
     | 
| 
      
 157 
     | 
    
         
            +
                    @show_input   ||= 1
         
     | 
| 
      
 158 
     | 
    
         
            +
                    @show_error   ||= 1
         
     | 
| 
      
 159 
     | 
    
         
            +
                  end
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                  def check_for_valid_input_params
         
     | 
| 
      
 162 
     | 
    
         
            +
                    check_parameter(self, valid_validation_parameter, 'data_validation')
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                    unless has_key?(:validate)
         
     | 
| 
      
 165 
     | 
    
         
            +
                      raise WriteXLSXOptionParameterError, "Parameter :validate is required in data_validation()"
         
     | 
| 
      
 166 
     | 
    
         
            +
                    end
         
     | 
| 
      
 167 
     | 
    
         
            +
                    unless valid_validation_type.has_key?(@validate.downcase)
         
     | 
| 
      
 168 
     | 
    
         
            +
                      raise WriteXLSXOptionParameterError,
         
     | 
| 
      
 169 
     | 
    
         
            +
                      "Unknown validation type '#{@validate}' for parameter :validate in data_validation()"
         
     | 
| 
      
 170 
     | 
    
         
            +
                    end
         
     | 
| 
      
 171 
     | 
    
         
            +
                    if @error_type && !error_type_hash.has_key?(@error_type.downcase)
         
     | 
| 
      
 172 
     | 
    
         
            +
                      raise WriteXLSXOptionParameterError,
         
     | 
| 
      
 173 
     | 
    
         
            +
                      "Unknown criteria type '#param[:error_type}' for parameter :error_type in data_validation()"
         
     | 
| 
      
 174 
     | 
    
         
            +
                    end
         
     | 
| 
      
 175 
     | 
    
         
            +
                  end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                  def check_criteria_required
         
     | 
| 
      
 178 
     | 
    
         
            +
                    unless has_key?(:criteria)
         
     | 
| 
      
 179 
     | 
    
         
            +
                      raise WriteXLSXOptionParameterError, "Parameter :criteria is required in data_validation()"
         
     | 
| 
      
 180 
     | 
    
         
            +
                    end
         
     | 
| 
      
 181 
     | 
    
         
            +
                  end
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                  def check_maximum_value_when_criteria_is_between_or_notbetween
         
     | 
| 
      
 184 
     | 
    
         
            +
                    if @criteria == 'between' || @criteria == 'notBetween'
         
     | 
| 
      
 185 
     | 
    
         
            +
                      unless has_key?(:maximum)
         
     | 
| 
      
 186 
     | 
    
         
            +
                        raise WriteXLSXOptionParameterError,
         
     | 
| 
      
 187 
     | 
    
         
            +
                        "Parameter :maximum is required in data_validation() when using :between or :not between criteria"
         
     | 
| 
      
 188 
     | 
    
         
            +
                      end
         
     | 
| 
      
 189 
     | 
    
         
            +
                    else
         
     | 
| 
      
 190 
     | 
    
         
            +
                      @maximum = nil
         
     | 
| 
      
 191 
     | 
    
         
            +
                    end
         
     | 
| 
      
 192 
     | 
    
         
            +
                  end
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                  def check_valid_citeria_types
         
     | 
| 
      
 195 
     | 
    
         
            +
                    unless valid_criteria_type.has_key?(@criteria.downcase)
         
     | 
| 
      
 196 
     | 
    
         
            +
                      raise WriteXLSXOptionParameterError,
         
     | 
| 
      
 197 
     | 
    
         
            +
                      "Unknown criteria type '#{@criteria}' for parameter :criteria in data_validation()"
         
     | 
| 
      
 198 
     | 
    
         
            +
                    end
         
     | 
| 
      
 199 
     | 
    
         
            +
                  end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
      
 201 
     | 
    
         
            +
                  def convert_date_time_value_if_required
         
     | 
| 
      
 202 
     | 
    
         
            +
                    @date_1904 = date_1904?
         
     | 
| 
      
 203 
     | 
    
         
            +
                    if @validate == 'date' || @validate == 'time'
         
     | 
| 
      
 204 
     | 
    
         
            +
                      unless convert_date_time_value(:value) && convert_date_time_value(:maximum)
         
     | 
| 
      
 205 
     | 
    
         
            +
                        raise WriteXLSXOptionParameterError, "Invalid date/time value."
         
     | 
| 
      
 206 
     | 
    
         
            +
                      end
         
     | 
| 
      
 207 
     | 
    
         
            +
                    end
         
     | 
| 
      
 208 
     | 
    
         
            +
                  end
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                  def error_type_hash
         
     | 
| 
      
 211 
     | 
    
         
            +
                    {'stop' => 0, 'warning' => 1, 'information' => 2}
         
     | 
| 
      
 212 
     | 
    
         
            +
                  end
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                  def valid_validation_type # :nodoc:
         
     | 
| 
      
 215 
     | 
    
         
            +
                    {
         
     | 
| 
      
 216 
     | 
    
         
            +
                      'any'             => 'none',
         
     | 
| 
      
 217 
     | 
    
         
            +
                      'any value'       => 'none',
         
     | 
| 
      
 218 
     | 
    
         
            +
                      'whole number'    => 'whole',
         
     | 
| 
      
 219 
     | 
    
         
            +
                      'whole'           => 'whole',
         
     | 
| 
      
 220 
     | 
    
         
            +
                      'integer'         => 'whole',
         
     | 
| 
      
 221 
     | 
    
         
            +
                      'decimal'         => 'decimal',
         
     | 
| 
      
 222 
     | 
    
         
            +
                      'list'            => 'list',
         
     | 
| 
      
 223 
     | 
    
         
            +
                      'date'            => 'date',
         
     | 
| 
      
 224 
     | 
    
         
            +
                      'time'            => 'time',
         
     | 
| 
      
 225 
     | 
    
         
            +
                      'text length'     => 'textLength',
         
     | 
| 
      
 226 
     | 
    
         
            +
                      'length'          => 'textLength',
         
     | 
| 
      
 227 
     | 
    
         
            +
                      'custom'          => 'custom'
         
     | 
| 
      
 228 
     | 
    
         
            +
                    }
         
     | 
| 
      
 229 
     | 
    
         
            +
                  end
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                  # List of valid input parameters.
         
     | 
| 
      
 232 
     | 
    
         
            +
                  def valid_validation_parameter
         
     | 
| 
      
 233 
     | 
    
         
            +
                    [
         
     | 
| 
      
 234 
     | 
    
         
            +
                     :validate,
         
     | 
| 
      
 235 
     | 
    
         
            +
                     :criteria,
         
     | 
| 
      
 236 
     | 
    
         
            +
                     :value,
         
     | 
| 
      
 237 
     | 
    
         
            +
                     :source,
         
     | 
| 
      
 238 
     | 
    
         
            +
                     :minimum,
         
     | 
| 
      
 239 
     | 
    
         
            +
                     :maximum,
         
     | 
| 
      
 240 
     | 
    
         
            +
                     :ignore_blank,
         
     | 
| 
      
 241 
     | 
    
         
            +
                     :dropdown,
         
     | 
| 
      
 242 
     | 
    
         
            +
                     :show_input,
         
     | 
| 
      
 243 
     | 
    
         
            +
                     :input_title,
         
     | 
| 
      
 244 
     | 
    
         
            +
                     :input_message,
         
     | 
| 
      
 245 
     | 
    
         
            +
                     :show_error,
         
     | 
| 
      
 246 
     | 
    
         
            +
                     :error_title,
         
     | 
| 
      
 247 
     | 
    
         
            +
                     :error_message,
         
     | 
| 
      
 248 
     | 
    
         
            +
                     :error_type,
         
     | 
| 
      
 249 
     | 
    
         
            +
                     :other_cells
         
     | 
| 
      
 250 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 251 
     | 
    
         
            +
                  end
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                  # List of valid criteria types.
         
     | 
| 
      
 254 
     | 
    
         
            +
                  def valid_criteria_type  # :nodoc:
         
     | 
| 
      
 255 
     | 
    
         
            +
                    {
         
     | 
| 
      
 256 
     | 
    
         
            +
                      'between'                     => 'between',
         
     | 
| 
      
 257 
     | 
    
         
            +
                      'not between'                 => 'notBetween',
         
     | 
| 
      
 258 
     | 
    
         
            +
                      'equal to'                    => 'equal',
         
     | 
| 
      
 259 
     | 
    
         
            +
                      '='                           => 'equal',
         
     | 
| 
      
 260 
     | 
    
         
            +
                      '=='                          => 'equal',
         
     | 
| 
      
 261 
     | 
    
         
            +
                      'not equal to'                => 'notEqual',
         
     | 
| 
      
 262 
     | 
    
         
            +
                      '!='                          => 'notEqual',
         
     | 
| 
      
 263 
     | 
    
         
            +
                      '<>'                          => 'notEqual',
         
     | 
| 
      
 264 
     | 
    
         
            +
                      'greater than'                => 'greaterThan',
         
     | 
| 
      
 265 
     | 
    
         
            +
                      '>'                           => 'greaterThan',
         
     | 
| 
      
 266 
     | 
    
         
            +
                      'less than'                   => 'lessThan',
         
     | 
| 
      
 267 
     | 
    
         
            +
                      '<'                           => 'lessThan',
         
     | 
| 
      
 268 
     | 
    
         
            +
                      'greater than or equal to'    => 'greaterThanOrEqual',
         
     | 
| 
      
 269 
     | 
    
         
            +
                      '>='                          => 'greaterThanOrEqual',
         
     | 
| 
      
 270 
     | 
    
         
            +
                      'less than or equal to'       => 'lessThanOrEqual',
         
     | 
| 
      
 271 
     | 
    
         
            +
                      '<='                          => 'lessThanOrEqual'
         
     | 
| 
      
 272 
     | 
    
         
            +
                    }
         
     | 
| 
      
 273 
     | 
    
         
            +
                  end
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
                  def convert_date_time_value(key)  # :nodoc:
         
     | 
| 
      
 276 
     | 
    
         
            +
                    value = instance_variable_get("@#{key}")
         
     | 
| 
      
 277 
     | 
    
         
            +
                    if value && value =~ /T/
         
     | 
| 
      
 278 
     | 
    
         
            +
                      date_time = convert_date_time(value)
         
     | 
| 
      
 279 
     | 
    
         
            +
                      instance_variable_set("@#{key}", date_time) if date_time
         
     | 
| 
      
 280 
     | 
    
         
            +
                      date_time
         
     | 
| 
      
 281 
     | 
    
         
            +
                    else
         
     | 
| 
      
 282 
     | 
    
         
            +
                      true
         
     | 
| 
      
 283 
     | 
    
         
            +
                    end
         
     | 
| 
      
 284 
     | 
    
         
            +
                  end
         
     | 
| 
      
 285 
     | 
    
         
            +
             
     | 
| 
      
 286 
     | 
    
         
            +
                  def date_1904?
         
     | 
| 
      
 287 
     | 
    
         
            +
                    @date_1904
         
     | 
| 
      
 288 
     | 
    
         
            +
                  end
         
     | 
| 
      
 289 
     | 
    
         
            +
                end
         
     | 
| 
      
 290 
     | 
    
         
            +
              end
         
     | 
| 
      
 291 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,111 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Writexlsx
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Worksheet
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Hyperlink   # :nodoc:
         
     | 
| 
      
 6 
     | 
    
         
            +
                  include Writexlsx::Utility
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :url, :link_type, :str, :url_str
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_accessor :tip, :display
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize(url, str = nil)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    link_type = 1
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    # Remove the URI scheme from internal links.
         
     | 
| 
      
 15 
     | 
    
         
            +
                    if url =~ /^internal:/
         
     | 
| 
      
 16 
     | 
    
         
            +
                      url = url.sub(/^internal:/, '')
         
     | 
| 
      
 17 
     | 
    
         
            +
                      link_type = 2
         
     | 
| 
      
 18 
     | 
    
         
            +
                      # Remove the URI scheme from external links.
         
     | 
| 
      
 19 
     | 
    
         
            +
                    elsif url =~ /^external:/
         
     | 
| 
      
 20 
     | 
    
         
            +
                      url = url.sub(/^external:/, '')
         
     | 
| 
      
 21 
     | 
    
         
            +
                      link_type = 3
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    # The displayed string defaults to the url string.
         
     | 
| 
      
 25 
     | 
    
         
            +
                    str ||= url.dup
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                    # For external links change the directory separator from Unix to Dos.
         
     | 
| 
      
 28 
     | 
    
         
            +
                    if link_type == 3
         
     | 
| 
      
 29 
     | 
    
         
            +
                      url = url.gsub(%r|/|, '\\')
         
     | 
| 
      
 30 
     | 
    
         
            +
                      str.gsub!(%r|/|, '\\')
         
     | 
| 
      
 31 
     | 
    
         
            +
                    end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                    # Strip the mailto header.
         
     | 
| 
      
 34 
     | 
    
         
            +
                    str.sub!(/^mailto:/, '')
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    # Copy string for use in hyperlink elements.
         
     | 
| 
      
 37 
     | 
    
         
            +
                    url_str = str.dup
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    # External links to URLs and to other Excel workbooks have slightly
         
     | 
| 
      
 40 
     | 
    
         
            +
                    # different characteristics that we have to account for.
         
     | 
| 
      
 41 
     | 
    
         
            +
                    if link_type == 1
         
     | 
| 
      
 42 
     | 
    
         
            +
                      # Escape URL unless it looks already escaped.
         
     | 
| 
      
 43 
     | 
    
         
            +
                      unless url =~ /%[0-9a-fA-F]{2}/
         
     | 
| 
      
 44 
     | 
    
         
            +
                        # Escape the URL escape symbol.
         
     | 
| 
      
 45 
     | 
    
         
            +
                        url = url.gsub(/%/, "%25")
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                        # Escape whitespae in URL.
         
     | 
| 
      
 48 
     | 
    
         
            +
                        url = url.gsub(/[\s\x00]/, '%20')
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                        # Escape other special characters in URL.
         
     | 
| 
      
 51 
     | 
    
         
            +
                        re = /(["<>\[\]`^{}])/
         
     | 
| 
      
 52 
     | 
    
         
            +
                        while re =~ url
         
     | 
| 
      
 53 
     | 
    
         
            +
                          match = $~[1]
         
     | 
| 
      
 54 
     | 
    
         
            +
                          url = url.sub(re, sprintf("%%%x", match.ord))
         
     | 
| 
      
 55 
     | 
    
         
            +
                        end
         
     | 
| 
      
 56 
     | 
    
         
            +
                      end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                      # Ordinary URL style external links don't have a "location" string.
         
     | 
| 
      
 59 
     | 
    
         
            +
                      url_str = nil
         
     | 
| 
      
 60 
     | 
    
         
            +
                    elsif link_type == 3
         
     | 
| 
      
 61 
     | 
    
         
            +
                      # External Workbook links need to be modified into the right format.
         
     | 
| 
      
 62 
     | 
    
         
            +
                      # The URL will look something like 'c:\temp\file.xlsx#Sheet!A1'.
         
     | 
| 
      
 63 
     | 
    
         
            +
                      # We need the part to the left of the # as the URL and the part to
         
     | 
| 
      
 64 
     | 
    
         
            +
                      # the right as the "location" string (if it exists).
         
     | 
| 
      
 65 
     | 
    
         
            +
                      url, url_str = url.split(/#/)
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                      # Add the file:/// URI to the url if non-local.
         
     | 
| 
      
 68 
     | 
    
         
            +
                      if url =~ %r![:]! ||        # Windows style "C:/" link.
         
     | 
| 
      
 69 
     | 
    
         
            +
                          url =~ %r!^\\\\!        # Network share.
         
     | 
| 
      
 70 
     | 
    
         
            +
                        url = "file:///#{url}"
         
     | 
| 
      
 71 
     | 
    
         
            +
                      end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                      # Convert a ./dir/file.xlsx link to dir/file.xlsx.
         
     | 
| 
      
 74 
     | 
    
         
            +
                      url = url.sub(%r!^.\\!, '')
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                      # Treat as a default external link now that the data has been modified.
         
     | 
| 
      
 77 
     | 
    
         
            +
                      link_type = 1
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                    # Excel limits escaped URL to 255 characters.
         
     | 
| 
      
 81 
     | 
    
         
            +
                    if url.bytesize > 255
         
     | 
| 
      
 82 
     | 
    
         
            +
                      raise "URL '#{url}' > 255 characters, it exceeds Excel's limit for URLS."
         
     | 
| 
      
 83 
     | 
    
         
            +
                    end
         
     | 
| 
      
 84 
     | 
    
         
            +
                    @url       = url
         
     | 
| 
      
 85 
     | 
    
         
            +
                    @link_type = link_type
         
     | 
| 
      
 86 
     | 
    
         
            +
                    @str       = str
         
     | 
| 
      
 87 
     | 
    
         
            +
                    @url_str   = url_str
         
     | 
| 
      
 88 
     | 
    
         
            +
                  end
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  def write_external_attributes(row, col, id)
         
     | 
| 
      
 91 
     | 
    
         
            +
                    ref = xl_rowcol_to_cell(row, col)
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                    attributes = ['ref', ref, 'r:id', "rId#{id}"]
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                    attributes << 'location' << url_str if url_str
         
     | 
| 
      
 96 
     | 
    
         
            +
                    attributes << 'display'  << display if display
         
     | 
| 
      
 97 
     | 
    
         
            +
                    attributes << 'tooltip'  << tip     if tip
         
     | 
| 
      
 98 
     | 
    
         
            +
                    attributes
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  def write_internal_attributes(row, col)
         
     | 
| 
      
 102 
     | 
    
         
            +
                    ref = xl_rowcol_to_cell(row, col)
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                    attributes = ['ref', ref, 'location', url]
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                    attributes << 'tooltip' << tip if tip
         
     | 
| 
      
 107 
     | 
    
         
            +
                    attributes << 'display' << str
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
            end
         
     |