write_xlsx 1.04.0 → 1.08.2

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.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/Changes +50 -0
  4. data/README.md +1 -1
  5. data/examples/chart_data_labels.rb +320 -0
  6. data/examples/ignore_errors.rb +39 -0
  7. data/ignore_errors.xlsx +0 -0
  8. data/lib/write_xlsx/chart/series.rb +100 -0
  9. data/lib/write_xlsx/chart.rb +155 -33
  10. data/lib/write_xlsx/drawing.rb +80 -17
  11. data/lib/write_xlsx/package/app.rb +3 -3
  12. data/lib/write_xlsx/package/conditional_format.rb +2 -8
  13. data/lib/write_xlsx/package/packager.rb +1 -0
  14. data/lib/write_xlsx/package/styles.rb +16 -3
  15. data/lib/write_xlsx/package/table.rb +8 -0
  16. data/lib/write_xlsx/utility.rb +9 -3
  17. data/lib/write_xlsx/version.rb +1 -1
  18. data/lib/write_xlsx/workbook.rb +23 -0
  19. data/lib/write_xlsx/worksheet/data_validation.rb +1 -6
  20. data/lib/write_xlsx/worksheet.rb +160 -37
  21. data/test/drawing/{test_write_ext.rb → test_write_xdr_ext.rb} +2 -2
  22. data/test/perl_output/chart_data_labels.xlsx +0 -0
  23. data/test/perl_output/ignore_errors.xlsx +0 -0
  24. data/test/regression/test_array_formula04.rb +31 -0
  25. data/test/regression/test_chart_crossing01.rb +1 -1
  26. data/test/regression/test_chart_crossing05.rb +46 -0
  27. data/test/regression/test_chart_crossing06.rb +46 -0
  28. data/test/regression/test_chart_data_labels26.rb +44 -0
  29. data/test/regression/test_chart_data_labels27.rb +44 -0
  30. data/test/regression/test_chart_data_labels28.rb +52 -0
  31. data/test/regression/test_chart_data_labels29.rb +43 -0
  32. data/test/regression/test_chart_data_labels30.rb +46 -0
  33. data/test/regression/test_chart_data_labels31.rb +49 -0
  34. data/test/regression/test_chart_data_labels32.rb +54 -0
  35. data/test/regression/test_chart_data_labels33.rb +52 -0
  36. data/test/regression/test_chart_data_labels34.rb +54 -0
  37. data/test/regression/test_chart_data_labels35.rb +46 -0
  38. data/test/regression/test_chart_data_labels36.rb +54 -0
  39. data/test/regression/test_chart_data_labels37.rb +51 -0
  40. data/test/regression/test_chart_data_labels38.rb +54 -0
  41. data/test/regression/test_chart_data_labels39.rb +53 -0
  42. data/test/regression/test_chart_data_labels40.rb +53 -0
  43. data/test/regression/test_chart_data_labels41.rb +54 -0
  44. data/test/regression/test_chart_data_labels42.rb +58 -0
  45. data/test/regression/test_chart_data_labels43.rb +58 -0
  46. data/test/regression/test_chart_data_labels44.rb +56 -0
  47. data/test/regression/test_chart_data_labels45.rb +57 -0
  48. data/test/regression/test_chart_data_labels46.rb +61 -0
  49. data/test/regression/test_chart_data_labels47.rb +61 -0
  50. data/test/regression/test_chart_data_labels48.rb +55 -0
  51. data/test/regression/test_chart_data_labels49.rb +55 -0
  52. data/test/regression/test_chart_data_labels50.rb +57 -0
  53. data/test/regression/test_format16.rb +24 -0
  54. data/test/regression/test_format17.rb +24 -0
  55. data/test/regression/test_header04.rb +30 -0
  56. data/test/regression/test_hyperlink50.rb +27 -0
  57. data/test/regression/test_hyperlink51.rb +27 -0
  58. data/test/regression/test_ignore_error01.rb +23 -0
  59. data/test/regression/test_ignore_error02.rb +24 -0
  60. data/test/regression/test_ignore_error03.rb +26 -0
  61. data/test/regression/test_ignore_error04.rb +26 -0
  62. data/test/regression/test_ignore_error05.rb +32 -0
  63. data/test/regression/test_ignore_error06.rb +32 -0
  64. data/test/regression/test_image52.rb +26 -0
  65. data/test/regression/test_image53.rb +26 -0
  66. data/test/regression/test_image54.rb +26 -0
  67. data/test/regression/test_image55.rb +27 -0
  68. data/test/regression/test_protect04.rb +32 -0
  69. data/test/regression/test_protect05.rb +35 -0
  70. data/test/regression/test_protect06.rb +35 -0
  71. data/test/regression/test_protect07.rb +23 -0
  72. data/test/regression/test_table26.rb +38 -0
  73. data/test/regression/xlsx_files/array_formula04.xlsx +0 -0
  74. data/test/regression/xlsx_files/chart_crossing05.xlsx +0 -0
  75. data/test/regression/xlsx_files/chart_crossing06.xlsx +0 -0
  76. data/test/regression/xlsx_files/chart_data_labels26.xlsx +0 -0
  77. data/test/regression/xlsx_files/chart_data_labels27.xlsx +0 -0
  78. data/test/regression/xlsx_files/chart_data_labels28.xlsx +0 -0
  79. data/test/regression/xlsx_files/chart_data_labels29.xlsx +0 -0
  80. data/test/regression/xlsx_files/chart_data_labels30.xlsx +0 -0
  81. data/test/regression/xlsx_files/chart_data_labels31.xlsx +0 -0
  82. data/test/regression/xlsx_files/chart_data_labels32.xlsx +0 -0
  83. data/test/regression/xlsx_files/chart_data_labels33.xlsx +0 -0
  84. data/test/regression/xlsx_files/chart_data_labels34.xlsx +0 -0
  85. data/test/regression/xlsx_files/chart_data_labels35.xlsx +0 -0
  86. data/test/regression/xlsx_files/chart_data_labels36.xlsx +0 -0
  87. data/test/regression/xlsx_files/chart_data_labels37.xlsx +0 -0
  88. data/test/regression/xlsx_files/chart_data_labels38.xlsx +0 -0
  89. data/test/regression/xlsx_files/chart_data_labels39.xlsx +0 -0
  90. data/test/regression/xlsx_files/chart_data_labels40.xlsx +0 -0
  91. data/test/regression/xlsx_files/chart_data_labels41.xlsx +0 -0
  92. data/test/regression/xlsx_files/chart_data_labels42.xlsx +0 -0
  93. data/test/regression/xlsx_files/chart_data_labels43.xlsx +0 -0
  94. data/test/regression/xlsx_files/chart_data_labels44.xlsx +0 -0
  95. data/test/regression/xlsx_files/chart_data_labels45.xlsx +0 -0
  96. data/test/regression/xlsx_files/chart_data_labels46.xlsx +0 -0
  97. data/test/regression/xlsx_files/chart_data_labels47.xlsx +0 -0
  98. data/test/regression/xlsx_files/chart_data_labels48.xlsx +0 -0
  99. data/test/regression/xlsx_files/chart_data_labels49.xlsx +0 -0
  100. data/test/regression/xlsx_files/chart_data_labels50.xlsx +0 -0
  101. data/test/regression/xlsx_files/format16.xlsx +0 -0
  102. data/test/regression/xlsx_files/format17.xlsx +0 -0
  103. data/test/regression/xlsx_files/header04.xlsx +0 -0
  104. data/test/regression/xlsx_files/hyperlink50.xlsx +0 -0
  105. data/test/regression/xlsx_files/hyperlink51.xlsx +0 -0
  106. data/test/regression/xlsx_files/ignore_error01.xlsx +0 -0
  107. data/test/regression/xlsx_files/ignore_error02.xlsx +0 -0
  108. data/test/regression/xlsx_files/ignore_error03.xlsx +0 -0
  109. data/test/regression/xlsx_files/ignore_error04.xlsx +0 -0
  110. data/test/regression/xlsx_files/ignore_error05.xlsx +0 -0
  111. data/test/regression/xlsx_files/ignore_error06.xlsx +0 -0
  112. data/test/regression/xlsx_files/image52.xlsx +0 -0
  113. data/test/regression/xlsx_files/image53.xlsx +0 -0
  114. data/test/regression/xlsx_files/image54.xlsx +0 -0
  115. data/test/regression/xlsx_files/image55.xlsx +0 -0
  116. data/test/regression/xlsx_files/protect04.xlsx +0 -0
  117. data/test/regression/xlsx_files/protect05.xlsx +0 -0
  118. data/test/regression/xlsx_files/protect06.xlsx +0 -0
  119. data/test/regression/xlsx_files/protect07.xlsx +0 -0
  120. data/test/regression/xlsx_files/table26.xlsx +0 -0
  121. data/test/test_example_match.rb +345 -1
  122. data/test/utility/test_range.rb +20 -0
  123. metadata +209 -8
@@ -52,6 +52,7 @@ module Writexlsx
52
52
  attr_reader :max_url_length # :nodoc:
53
53
  attr_reader :strings_to_urls # :nodoc:
54
54
  attr_reader :default_url_format # :nodoc:
55
+ attr_reader :read_only # :nodoc:
55
56
 
56
57
  #
57
58
  # A new Excel workbook is created using the +new+ constructor
@@ -133,6 +134,7 @@ module Writexlsx
133
134
 
134
135
  @max_url_length = 2079
135
136
  @has_comments = false
137
+ @read_only = 0
136
138
  if options[:max_url_length]
137
139
  @max_url_length = options[:max_url_length]
138
140
 
@@ -292,6 +294,9 @@ module Writexlsx
292
294
  # Write the XLSX file version.
293
295
  write_file_version
294
296
 
297
+ # Write the fileSharing element.
298
+ write_file_sharing
299
+
295
300
  # Write the workbook properties.
296
301
  write_workbook_pr
297
302
 
@@ -954,6 +959,13 @@ module Writexlsx
954
959
  end
955
960
  end
956
961
 
962
+ #
963
+ # Set the Excel "Read-only recommended" save option.
964
+ #
965
+ def read_only_recommended
966
+ @read_only = 2
967
+ end
968
+
957
969
  #
958
970
  # set_calc_mode()
959
971
  #
@@ -1311,6 +1323,17 @@ module Writexlsx
1311
1323
  @writer.empty_tag('fileVersion', attributes)
1312
1324
  end
1313
1325
 
1326
+ #
1327
+ # Write the <fileSharing> element.
1328
+ #
1329
+ def write_file_sharing
1330
+ return if !ptrue?(@read_only)
1331
+
1332
+ attributes = []
1333
+ attributes << ['readOnlyRecommended', 1]
1334
+ @writer.empty_tag('fileSharing', attributes)
1335
+ end
1336
+
1314
1337
  def write_workbook_pr #:nodoc:
1315
1338
  attributes = []
1316
1339
  attributes << ['codeName', @vba_codename] if ptrue?(@vba_codename)
@@ -138,12 +138,7 @@ module Writexlsx
138
138
  row_first, row_last = row_last, row_first if row_first > row_last
139
139
  col_first, col_last = col_last, col_first if col_first > col_last
140
140
 
141
- # If the first and last cell are the same write a single cell.
142
- if row_first == row_last && col_first == col_last
143
- sqref += xl_rowcol_to_cell(row_first, col_first)
144
- else
145
- sqref += xl_range(row_first, row_last, col_first, col_last)
146
- end
141
+ sqref += xl_range(row_first, row_last, col_first, col_last)
147
142
  end
148
143
 
149
144
  if @validate != 'none'
@@ -381,6 +381,7 @@ module Writexlsx
381
381
  @comments = Package::Comments.new(self)
382
382
  @buttons_array = []
383
383
  @header_images_array = []
384
+ @ignore_errors = nil
384
385
 
385
386
  @validations = []
386
387
 
@@ -388,6 +389,9 @@ module Writexlsx
388
389
  @data_bars_2010 = []
389
390
  @dxf_priority = 1
390
391
 
392
+ @protected_ranges = []
393
+ @num_protected_ranges = 0
394
+
391
395
  if excel2003_style?
392
396
  @original_row_height = 12.75
393
397
  @default_row_height = 12.75
@@ -414,6 +418,7 @@ module Writexlsx
414
418
  write_cols
415
419
  write_sheet_data
416
420
  write_sheet_protection
421
+ write_protected_ranges
417
422
  # write_sheet_calc_pr
418
423
  write_phonetic_pr if excel2003_style?
419
424
  write_auto_filter
@@ -427,6 +432,7 @@ module Writexlsx
427
432
  write_header_footer
428
433
  write_row_breaks
429
434
  write_col_breaks
435
+ write_ignored_errors
430
436
  write_drawings
431
437
  write_legacy_drawing
432
438
  write_legacy_drawing_hf
@@ -616,7 +622,25 @@ module Writexlsx
616
622
 
617
623
  # Set the password after the user defined values.
618
624
  @protect[:password] =
619
- sprintf("%X", encode_password(password)) if password && password != ''
625
+ encode_password(password) if password && password != ''
626
+ end
627
+
628
+ #
629
+ # Unprotect ranges within a protected worksheet.
630
+ #
631
+ def unprotect_range(range, range_name = nil, password = nil)
632
+ if range.nil?
633
+ raise "The range must be defined in unprotect_range())\n"
634
+ else
635
+ range.gsub!(/\$/, "")
636
+ range.sub!(/^=/, "")
637
+ @num_protected_ranges += 1
638
+ end
639
+
640
+ range_name ||= "Range#{@num_protected_ranges}"
641
+ password &&= encode_password(password)
642
+
643
+ @protected_ranges << [range, range_name, password]
620
644
  end
621
645
 
622
646
  def protect_default_settings # :nodoc:
@@ -818,12 +842,7 @@ module Writexlsx
818
842
  row_first, row_last = row_last, row_first if row_first > row_last
819
843
  col_first, col_last = col_last, col_first if col_first > col_last
820
844
 
821
- # If the first and last cell are the same write a single cell.
822
- if row_first == row_last && col_first == col_last
823
- sqref = active_cell
824
- else
825
- sqref = xl_range(row_first, row_last, col_first, col_last)
826
- end
845
+ sqref = xl_range(row_first, row_last, col_first, col_last)
827
846
  else # Single cell selection.
828
847
  sqref = active_cell
829
848
  end
@@ -1207,14 +1226,10 @@ module Writexlsx
1207
1226
  # distribution.
1208
1227
  #
1209
1228
  def set_header(string = '', margin = 0.3, options = {})
1210
- raise 'Header string must be less than 255 characters' if string.length >= 255
1229
+ raise 'Header string must be less than 255 characters' if string.length > 255
1211
1230
  # Replace the Excel placeholder &[Picture] with the internal &G.
1212
1231
  @page_setup.header = string.gsub(/&\[Picture\]/, '&G')
1213
1232
 
1214
- if string.size >= 255
1215
- raise 'Header string must be less than 255 characters'
1216
- end
1217
-
1218
1233
  if options[:align_with_margins]
1219
1234
  @page_setup.header_footer_aligns = options[:align_with_margins]
1220
1235
  end
@@ -1255,17 +1270,13 @@ module Writexlsx
1255
1270
  # The syntax of the set_footer() method is the same as set_header()
1256
1271
  #
1257
1272
  def set_footer(string = '', margin = 0.3, options = {})
1258
- raise 'Footer string must be less than 255 characters' if string.length >= 255
1273
+ raise 'Footer string must be less than 255 characters' if string.length > 255
1259
1274
 
1260
1275
  @page_setup.footer = string.dup
1261
1276
 
1262
1277
  # Replace the Excel placeholder &[Picture] with the internal &G.
1263
1278
  @page_setup.footer = string.gsub(/&\[Picture\]/, '&G')
1264
1279
 
1265
- if string.size >= 255
1266
- raise 'Header string must be less than 255 characters'
1267
- end
1268
-
1269
1280
  if options[:align_with_margins]
1270
1281
  @page_setup.header_footer_aligns = options[:align_with_margins]
1271
1282
  end
@@ -2514,7 +2525,9 @@ module Writexlsx
2514
2525
  col1, col2 = col2, col1 if col1 > col2
2515
2526
 
2516
2527
  # Check that row and col are valid and store max and min values
2528
+ check_dimensions(row1, col1)
2517
2529
  check_dimensions(row2, col2)
2530
+ store_row_col_max_min_values(row1, col1)
2518
2531
  store_row_col_max_min_values(row2, col2)
2519
2532
 
2520
2533
  # Define array range
@@ -3046,14 +3059,16 @@ module Writexlsx
3046
3059
 
3047
3060
  if options.first.class == Hash
3048
3061
  # Newer hash bashed options
3049
- params = options.first
3050
- x_offset = params[:x_offset]
3051
- y_offset = params[:y_offset]
3052
- x_scale = params[:x_scale]
3053
- y_scale = params[:y_scale]
3054
- anchor = params[:object_position]
3055
- url = params[:url]
3056
- tip = params[:tip]
3062
+ params = options.first
3063
+ x_offset = params[:x_offset]
3064
+ y_offset = params[:y_offset]
3065
+ x_scale = params[:x_scale]
3066
+ y_scale = params[:y_scale]
3067
+ anchor = params[:object_position]
3068
+ url = params[:url]
3069
+ tip = params[:tip]
3070
+ description = params[:description]
3071
+ decorative = params[:decorative]
3057
3072
  else
3058
3073
  x_offset, y_offset, x_scale, y_scale, anchor = options
3059
3074
  end
@@ -3065,7 +3080,7 @@ module Writexlsx
3065
3080
 
3066
3081
  @images << [
3067
3082
  row, col, image, x_offset, y_offset,
3068
- x_scale, y_scale, url, tip, anchor
3083
+ x_scale, y_scale, url, tip, anchor, description, decorative
3069
3084
  ]
3070
3085
  end
3071
3086
 
@@ -3363,9 +3378,11 @@ module Writexlsx
3363
3378
  row_first, row_last = row_last, row_first if row_first > row_last
3364
3379
  col_first, col_last = col_last, col_first if col_first > col_last
3365
3380
 
3366
- # Check that column number is valid and store the max value
3367
- check_dimensions(row_last, col_last)
3368
- store_row_col_max_min_values(row_last, col_last)
3381
+ # Check that the data range is valid and store the max and min values.
3382
+ check_dimensions(row_first, col_first)
3383
+ check_dimensions(row_last, col_last)
3384
+ store_row_col_max_min_values(row_first, col_first)
3385
+ store_row_col_max_min_values(row_last, col_last)
3369
3386
 
3370
3387
  # Store the merge range.
3371
3388
  @merge << [row_first, col_first, row_last, col_last]
@@ -3428,9 +3445,11 @@ module Writexlsx
3428
3445
  row_first, row_last = row_last, row_first if row_first > row_last
3429
3446
  col_first, col_last = col_last, col_first if col_first > col_last
3430
3447
 
3431
- # Check that column number is valid and store the max value
3432
- check_dimensions(row_last, col_last)
3433
- store_row_col_max_min_values(row_last, col_last)
3448
+ # Check that the data range is valid and store the max and min values.
3449
+ check_dimensions(row_first, col_first)
3450
+ check_dimensions(row_last, col_last)
3451
+ store_row_col_max_min_values(row_first, col_first)
3452
+ store_row_col_max_min_values(row_last, col_last)
3434
3453
 
3435
3454
  # Store the merge range.
3436
3455
  @merge << [row_first, col_first, row_last, col_last]
@@ -5738,7 +5757,7 @@ module Writexlsx
5738
5757
  name = chart.name
5739
5758
 
5740
5759
  # Create a Drawing object to use with worksheet unless one already exists.
5741
- drawing = Drawing.new(drawing_type, dimensions, 0, 0, name, nil, anchor, drawing_rel_index, 0, nil)
5760
+ drawing = Drawing.new(drawing_type, dimensions, 0, 0, name, nil, anchor, drawing_rel_index, 0, nil, 0)
5742
5761
  if !drawings?
5743
5762
  @drawings = Drawings.new
5744
5763
  @drawings.add_drawing_object(drawing)
@@ -6062,6 +6081,30 @@ module Writexlsx
6062
6081
  end
6063
6082
  end
6064
6083
 
6084
+ #
6085
+ # Ignore worksheet errors/warnings in user defined ranges.
6086
+ #
6087
+ def ignore_errors(ignores)
6088
+ # List of valid input parameters.
6089
+ valid_parameter_keys = [
6090
+ :number_stored_as_text,
6091
+ :eval_error,
6092
+ :formula_differs,
6093
+ :formula_range,
6094
+ :formula_unlocked,
6095
+ :empty_cell_reference,
6096
+ :list_data_validation,
6097
+ :calculated_column,
6098
+ :two_digit_text_year
6099
+ ]
6100
+
6101
+ unless (ignores.keys - valid_parameter_keys).empty?
6102
+ raise "Unknown parameter '#{ignores.key - valid_parameter_keys}' in ignore_errors()."
6103
+ end
6104
+
6105
+ @ignore_errors = ignores
6106
+ end
6107
+
6065
6108
  def write_ext(url)
6066
6109
  attributes = [
6067
6110
  ['xmlns:x14', "#{OFFICE_URL}spreadsheetml/2009/9/main"],
@@ -6464,7 +6507,7 @@ module Writexlsx
6464
6507
  drawing_type = 2
6465
6508
 
6466
6509
  row, col, image, x_offset, y_offset,
6467
- x_scale, y_scale, url, tip, anchor = @images[index]
6510
+ x_scale, y_scale, url, tip, anchor, description, decorative = @images[index]
6468
6511
 
6469
6512
  width *= x_scale
6470
6513
  height *= y_scale
@@ -6479,7 +6522,7 @@ module Writexlsx
6479
6522
  height = (0.5 + (height * 9_525)).to_i
6480
6523
 
6481
6524
  # Create a Drawing object to use with worksheet unless one already exists.
6482
- drawing = Drawing.new(drawing_type, dimensions, width, height, name, nil, anchor, 0, 0, tip)
6525
+ drawing = Drawing.new(drawing_type, dimensions, width, height, name, nil, anchor, 0, 0, tip, decorative)
6483
6526
  if !drawings?
6484
6527
  drawings = Drawings.new
6485
6528
  drawings.embedded = 1
@@ -6492,6 +6535,10 @@ module Writexlsx
6492
6535
  end
6493
6536
  drawings.add_drawing_object(drawing)
6494
6537
 
6538
+ if description
6539
+ drawing.description = description
6540
+ end
6541
+
6495
6542
  if url
6496
6543
  rel_type = '/hyperlink'
6497
6544
  target_mode = 'External'
@@ -6499,10 +6546,19 @@ module Writexlsx
6499
6546
  target = escape_url(url)
6500
6547
  end
6501
6548
  if url =~ /^external:/
6502
- target = escape_url(url.sub(/^external:/, 'file:///'))
6549
+ target = escape_url(url.sub(/^external:/, ''))
6550
+
6503
6551
  # Additional escape not required in worksheet hyperlinks
6504
6552
  target = target.gsub(/#/, '%23')
6553
+
6554
+ # Prefix absolute paths (not relative) with file:///
6555
+ if target =~ /^\w:/ || target =~ /^\\\\/
6556
+ target = "file:///#{target}"
6557
+ else
6558
+ target = target.gsub(/\\/, '/')
6559
+ end
6505
6560
  end
6561
+
6506
6562
  if url =~ /^internal:/
6507
6563
  target = url.sub(/^internal:/, '#')
6508
6564
  target_mode = nil
@@ -6645,7 +6701,7 @@ EOS
6645
6701
  shape.calc_position_emus(self)
6646
6702
 
6647
6703
  drawing_type = 3
6648
- drawing = Drawing.new(drawing_type, shape.dimensions, shape.width_emu, shape.height_emu, shape.name, shape, shape.anchor, drawing_rel_index, 0, nil)
6704
+ drawing = Drawing.new(drawing_type, shape.dimensions, shape.width_emu, shape.height_emu, shape.name, shape, shape.anchor, drawing_rel_index, 0, nil, 0)
6649
6705
  drawings.add_drawing_object(drawing)
6650
6706
  end
6651
6707
  public :prepare_shape
@@ -6735,6 +6791,8 @@ EOS
6735
6791
  chars.each { |c| encoded_password ^= c }
6736
6792
  encoded_password ^= count
6737
6793
  encoded_password ^= 0xCE4B
6794
+
6795
+ sprintf("%X", encoded_password)
6738
6796
  end
6739
6797
 
6740
6798
  #
@@ -7550,6 +7608,32 @@ EOS
7550
7608
  @writer.empty_tag('sheetProtection', attributes)
7551
7609
  end
7552
7610
 
7611
+ #
7612
+ # Write the <protectedRanges> element.
7613
+ #
7614
+ def write_protected_ranges
7615
+ return if @num_protected_ranges == 0
7616
+
7617
+ @writer.tag_elements('protectedRanges') do
7618
+ @protected_ranges.each do |protected_range|
7619
+ write_protected_range(*protected_range)
7620
+ end
7621
+ end
7622
+ end
7623
+
7624
+ #
7625
+ # Write the <protectedRange> element.
7626
+ #
7627
+ def write_protected_range(sqref, name, password)
7628
+ attributes = []
7629
+
7630
+ attributes << ['password', password] if password
7631
+ attributes << ['sqref', sqref]
7632
+ attributes << ['name', name]
7633
+
7634
+ @writer.empty_tag('protectedRange', attributes)
7635
+ end
7636
+
7553
7637
  #
7554
7638
  # Write the <drawing> elements.
7555
7639
  #
@@ -8082,5 +8166,44 @@ EOS
8082
8166
  end
8083
8167
  col
8084
8168
  end
8169
+
8170
+ #
8171
+ # Write the <ignoredErrors> element.
8172
+ #
8173
+ def write_ignored_errors
8174
+ return unless @ignore_errors
8175
+
8176
+ ignore = @ignore_errors
8177
+
8178
+ @writer.tag_elements('ignoredErrors' ) do
8179
+ {
8180
+ :number_stored_as_text => 'numberStoredAsText',
8181
+ :eval_error => 'evalError',
8182
+ :formula_differs => 'formula',
8183
+ :formula_range => 'formulaRange',
8184
+ :formula_unlocked => 'unlockedFormula',
8185
+ :empty_cell_reference => 'emptyCellReference',
8186
+ :list_data_validation => 'listDataValidation',
8187
+ :calculated_column => 'calculatedColumn',
8188
+ :two_digit_text_year => 'twoDigitTextYear'
8189
+ }.each do |key, value|
8190
+ if ignore[key]
8191
+ write_ignored_error(value, ignore[key])
8192
+ end
8193
+ end
8194
+ end
8195
+ end
8196
+
8197
+ #
8198
+ # Write the <ignoredError> element.
8199
+ #
8200
+ def write_ignored_error(type, sqref)
8201
+ attributes = {
8202
+ 'sqref' => sqref,
8203
+ type => 1
8204
+ }
8205
+
8206
+ @writer.empty_tag('ignoredError', attributes)
8207
+ end
8085
8208
  end
8086
8209
  end
@@ -2,7 +2,7 @@
2
2
  require 'helper'
3
3
  require 'write_xlsx/drawing'
4
4
 
5
- class TestWriteExt < Minitest::Test
5
+ class TestWriteXdrExt < Minitest::Test
6
6
  def setup
7
7
  @drawing = Writexlsx::Drawings.new
8
8
  end
@@ -10,7 +10,7 @@ class TestWriteExt < Minitest::Test
10
10
  def test_write_ext
11
11
  expected = '<xdr:ext cx="9308969" cy="6078325"/>'
12
12
 
13
- @drawing.__send__(:write_ext, 9308969, 6078325)
13
+ @drawing.__send__(:write_xdr_ext, 9308969, 6078325)
14
14
  result = @drawing.instance_variable_get(:@writer).string
15
15
 
16
16
  assert_equal(expected, result)
Binary file
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ class TestRegressionArrayFormula04 < Minitest::Test
5
+ def setup
6
+ setup_dir_var
7
+ end
8
+
9
+ def teardown
10
+ @tempfile.close(true)
11
+ end
12
+
13
+ def test_array_formula04
14
+ @xlsx = 'array_formula04.xlsx'
15
+ workbook = WriteXLSX.new(@io)
16
+ worksheet = workbook.add_worksheet
17
+
18
+ worksheet.write_array_formula(
19
+ 'A1:A3',
20
+ '{=SUM(B1:C1*B2:C2)}',
21
+ nil,
22
+ 0
23
+ )
24
+
25
+ workbook.close
26
+ compare_for_regression(
27
+ [ 'xl/calcChain.xml', '[Content_Types].xml', 'xl/_rels/workbook.xml.rels' ],
28
+ {'xl/workbook.xml' => ['<workbookView']}
29
+ )
30
+ end
31
+ end
@@ -33,7 +33,7 @@ class TestRegressionChartCrossing01 < Minitest::Test
33
33
 
34
34
  chart.set_y_axis(:crossing => 'max')
35
35
 
36
- # Not stictly required. Just to match reference file.
36
+ # Not strictly required. Just to match reference file.
37
37
  chart.set_x_axis(:position => 't')
38
38
 
39
39
  worksheet.insert_chart('E9', chart)
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ class TestRegressionChartCrossing05 < Minitest::Test
5
+ def setup
6
+ setup_dir_var
7
+ end
8
+
9
+ def teardown
10
+ @tempfile.close(true)
11
+ end
12
+
13
+ def test_chart_crossing05
14
+ @xlsx = 'chart_crossing05.xlsx'
15
+ workbook = WriteXLSX.new(@io)
16
+ worksheet = workbook.add_worksheet
17
+ chart = workbook.add_chart(:type => 'column', :embedded => 1)
18
+
19
+ # For testing, copy the randomly generated axis ids in the target xlsx file.
20
+ chart.instance_variable_set(:@axis_ids, [55948032, 55950336])
21
+
22
+ data = [
23
+ [1, 2, 3, 4, 5],
24
+ [2, 4, 6, 8, 10],
25
+ [3, 6, 9, 12, 15]
26
+ ]
27
+
28
+ worksheet.write('A1', data)
29
+
30
+ chart.add_series(:values => '=Sheet1!$A$1:$A$5')
31
+ chart.add_series(:values => '=Sheet1!$B$1:$B$5')
32
+ chart.add_series(:values => '=Sheet1!$C$1:$C$5')
33
+
34
+ chart.set_x_axis(:crossing => 'min')
35
+
36
+ worksheet.insert_chart('E9', chart)
37
+
38
+ workbook.close
39
+ compare_for_regression(
40
+ nil,
41
+ {
42
+ 'xl/charts/chart1.xml' => [ '<c:pageMargins' ]
43
+ }
44
+ )
45
+ end
46
+ end
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ class TestRegressionChartCrossing06 < Minitest::Test
5
+ def setup
6
+ setup_dir_var
7
+ end
8
+
9
+ def teardown
10
+ @tempfile.close(true)
11
+ end
12
+
13
+ def test_chart_crossing06
14
+ @xlsx = 'chart_crossing06.xlsx'
15
+ workbook = WriteXLSX.new(@io)
16
+ worksheet = workbook.add_worksheet
17
+ chart = workbook.add_chart(:type => 'column', :embedded => 1)
18
+
19
+ # For testing, copy the randomly generated axis ids in the target xlsx file.
20
+ chart.instance_variable_set(:@axis_ids, [72794880, 72796416])
21
+
22
+ data = [
23
+ [1, 2, 3, 4, 5],
24
+ [2, 4, 6, 8, 10],
25
+ [3, 6, 9, 12, 15]
26
+ ]
27
+
28
+ worksheet.write('A1', data)
29
+
30
+ chart.add_series(:values => '=Sheet1!$A$1:$A$5')
31
+ chart.add_series(:values => '=Sheet1!$B$1:$B$5')
32
+ chart.add_series(:values => '=Sheet1!$C$1:$C$5')
33
+
34
+ chart.set_y_axis(:crossing => 'min')
35
+
36
+ worksheet.insert_chart('E9', chart)
37
+
38
+ workbook.close
39
+ compare_for_regression(
40
+ nil,
41
+ {
42
+ 'xl/charts/chart1.xml' => [ '<c:pageMargins' ]
43
+ }
44
+ )
45
+ end
46
+ end
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ class TestRegressionChartDataLabels26 < Minitest::Test
5
+ def setup
6
+ setup_dir_var
7
+ end
8
+
9
+ def teardown
10
+ @tempfile.close(true)
11
+ end
12
+
13
+ def test_chart_data_labels26
14
+ @xlsx = 'chart_data_labels26.xlsx'
15
+ workbook = WriteXLSX.new(@io)
16
+ worksheet = workbook.add_worksheet
17
+ chart = workbook.add_chart(:type => 'column', :embedded => 1)
18
+
19
+ # For testing, copy the randomly generated axis ids in the target xlsx file.
20
+ chart.instance_variable_set(:@axis_ids, [48514944, 48516480])
21
+
22
+ data = [
23
+ [ 1, 2, 3, 4, 5],
24
+ [ 2, 4, 6, 8, 10],
25
+ [ 3, 6, 9, 12, 15],
26
+ [10, 20, 30, 40, 50]
27
+ ]
28
+
29
+ worksheet.write('A1', data)
30
+
31
+ chart.add_series(
32
+ :values => '=Sheet1!$A$1:$A$5',
33
+ :data_labels => {:value => 1, :custom => [{:value => 33}]}
34
+ )
35
+
36
+ chart.add_series(:values => '=Sheet1!$B$1:$B$5')
37
+ chart.add_series(:values => '=Sheet1!$C$1:$C$5')
38
+
39
+ worksheet.insert_chart('E9', chart)
40
+
41
+ workbook.close
42
+ compare_for_regression
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ class TestRegressionChartDataLabels27 < Minitest::Test
5
+ def setup
6
+ setup_dir_var
7
+ end
8
+
9
+ def teardown
10
+ @tempfile.close(true)
11
+ end
12
+
13
+ def test_chart_data_labels27
14
+ @xlsx = 'chart_data_labels27.xlsx'
15
+ workbook = WriteXLSX.new(@io)
16
+ worksheet = workbook.add_worksheet
17
+ chart = workbook.add_chart(:type => 'column', :embedded => 1)
18
+
19
+ # For testing, copy the randomly generated axis ids in the target xlsx file.
20
+ chart.instance_variable_set(:@axis_ids, [48514944, 48516480])
21
+
22
+ data = [
23
+ [ 1, 2, 3, 4, 5],
24
+ [ 2, 4, 6, 8, 10],
25
+ [ 3, 6, 9, 12, 15],
26
+ [10, 20, 30, 40, 50]
27
+ ]
28
+
29
+ worksheet.write('A1', data)
30
+
31
+ chart.add_series(
32
+ :values => '=Sheet1!$A$1:$A$5',
33
+ :data_labels => {:value => 1, :custom => [{:value => '=Sheet1!$D$1'}]}
34
+ )
35
+
36
+ chart.add_series(:values => '=Sheet1!$B$1:$B$5')
37
+ chart.add_series(:values => '=Sheet1!$C$1:$C$5')
38
+
39
+ worksheet.insert_chart('E9', chart)
40
+
41
+ workbook.close
42
+ compare_for_regression
43
+ end
44
+ end