write_xlsx 1.04.0 → 1.07.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/Changes +19 -0
  4. data/README.md +1 -1
  5. data/examples/chart_data_labels.rb +320 -0
  6. data/lib/write_xlsx/chart.rb +152 -28
  7. data/lib/write_xlsx/chart/series.rb +100 -0
  8. data/lib/write_xlsx/utility.rb +4 -2
  9. data/lib/write_xlsx/version.rb +1 -1
  10. data/lib/write_xlsx/worksheet.rb +12 -6
  11. data/test/perl_output/chart_data_labels.xlsx +0 -0
  12. data/test/regression/test_array_formula04.rb +31 -0
  13. data/test/regression/test_chart_data_labels26.rb +44 -0
  14. data/test/regression/test_chart_data_labels27.rb +44 -0
  15. data/test/regression/test_chart_data_labels28.rb +52 -0
  16. data/test/regression/test_chart_data_labels29.rb +43 -0
  17. data/test/regression/test_chart_data_labels30.rb +46 -0
  18. data/test/regression/test_chart_data_labels31.rb +49 -0
  19. data/test/regression/test_chart_data_labels32.rb +54 -0
  20. data/test/regression/test_chart_data_labels33.rb +52 -0
  21. data/test/regression/test_chart_data_labels34.rb +54 -0
  22. data/test/regression/test_chart_data_labels35.rb +46 -0
  23. data/test/regression/test_chart_data_labels36.rb +54 -0
  24. data/test/regression/test_chart_data_labels37.rb +51 -0
  25. data/test/regression/test_chart_data_labels38.rb +54 -0
  26. data/test/regression/test_chart_data_labels39.rb +53 -0
  27. data/test/regression/test_chart_data_labels40.rb +53 -0
  28. data/test/regression/test_chart_data_labels41.rb +54 -0
  29. data/test/regression/test_chart_data_labels42.rb +58 -0
  30. data/test/regression/test_chart_data_labels43.rb +58 -0
  31. data/test/regression/test_chart_data_labels44.rb +56 -0
  32. data/test/regression/test_chart_data_labels45.rb +57 -0
  33. data/test/regression/test_chart_data_labels46.rb +61 -0
  34. data/test/regression/test_chart_data_labels47.rb +61 -0
  35. data/test/regression/xlsx_files/array_formula04.xlsx +0 -0
  36. data/test/regression/xlsx_files/chart_data_labels26.xlsx +0 -0
  37. data/test/regression/xlsx_files/chart_data_labels27.xlsx +0 -0
  38. data/test/regression/xlsx_files/chart_data_labels28.xlsx +0 -0
  39. data/test/regression/xlsx_files/chart_data_labels29.xlsx +0 -0
  40. data/test/regression/xlsx_files/chart_data_labels30.xlsx +0 -0
  41. data/test/regression/xlsx_files/chart_data_labels31.xlsx +0 -0
  42. data/test/regression/xlsx_files/chart_data_labels32.xlsx +0 -0
  43. data/test/regression/xlsx_files/chart_data_labels33.xlsx +0 -0
  44. data/test/regression/xlsx_files/chart_data_labels34.xlsx +0 -0
  45. data/test/regression/xlsx_files/chart_data_labels35.xlsx +0 -0
  46. data/test/regression/xlsx_files/chart_data_labels36.xlsx +0 -0
  47. data/test/regression/xlsx_files/chart_data_labels37.xlsx +0 -0
  48. data/test/regression/xlsx_files/chart_data_labels38.xlsx +0 -0
  49. data/test/regression/xlsx_files/chart_data_labels39.xlsx +0 -0
  50. data/test/regression/xlsx_files/chart_data_labels40.xlsx +0 -0
  51. data/test/regression/xlsx_files/chart_data_labels41.xlsx +0 -0
  52. data/test/regression/xlsx_files/chart_data_labels42.xlsx +0 -0
  53. data/test/regression/xlsx_files/chart_data_labels43.xlsx +0 -0
  54. data/test/regression/xlsx_files/chart_data_labels44.xlsx +0 -0
  55. data/test/regression/xlsx_files/chart_data_labels45.xlsx +0 -0
  56. data/test/regression/xlsx_files/chart_data_labels46.xlsx +0 -0
  57. data/test/regression/xlsx_files/chart_data_labels47.xlsx +0 -0
  58. data/test/test_example_match.rb +314 -1
  59. metadata +97 -2
@@ -296,10 +296,110 @@ def labels_properties(labels) # :nodoc:
296
296
  labels[:separator] = separators[separator]
297
297
  end
298
298
 
299
+
300
+ # Set the line properties for the data labels.
301
+ line = line_properties( labels[:line] )
302
+
303
+ # Allow 'border' as a synonym for 'line'.
304
+ if labels[:border]
305
+ line = line_properties(labels[:border])
306
+ end
307
+
308
+ # Set the fill properties for the labels.
309
+ fill = fill_properties(labels[:fill])
310
+
311
+ # Set the pattern properties for the labels.
312
+ pattern = pattern_properties(labels[:pattern])
313
+
314
+ # Set the gradient fill properties for the labels.
315
+ gradient = gradient_properties(labels[:gradient])
316
+
317
+ # Pattern fill overrides solid fill.
318
+ if pattern
319
+ fill = nil
320
+ end
321
+
322
+ # Gradient fill overrides solid and pattern fills.
323
+ if gradient
324
+ pattern = nil
325
+ fill = nil
326
+ end
327
+
328
+ labels[:line] = line
329
+ labels[:fill] = fill
330
+ labels[:pattern] = pattern
331
+ labels[:gradient] = gradient
332
+
299
333
  if labels[:font]
300
334
  labels[:font] = convert_font_args(labels[:font])
301
335
  end
302
336
 
337
+ if labels[:custom]
338
+ # Duplicate, and modify, the custom label properties.
339
+ custom = []
340
+
341
+ labels[:custom].each do |label|
342
+ if !label
343
+ custom << nil
344
+ next
345
+ end
346
+
347
+ property = label.dup
348
+
349
+ # Convert formula.
350
+ if property[:value] && property[:value] =~ /^=[^!]+!\$/
351
+ property[:formula] = property[:value]
352
+ end
353
+
354
+ if property[:formula]
355
+ property[:formula] = property[:formula].sub(/^=/, '')
356
+
357
+ data_id = @chart.data_id(property[:formula], property[:data])
358
+ property[:data_id] = data_id
359
+ end
360
+
361
+ if property[:font]
362
+ property[:font] = convert_font_args(property[:font])
363
+ end
364
+
365
+ # Allow 'border' as a synonym for 'line'.
366
+ if property[:border]
367
+ line = line_properties(property[:border])
368
+ else
369
+ # Set the line properties for the data labels.
370
+ line = line_properties(property[:line])
371
+ end
372
+
373
+ # Set the fill properties for the labels.
374
+ fill = fill_properties(property[:fill])
375
+
376
+ # Set the pattern properties for the labels.
377
+ pattern = pattern_properties(property[:pattern])
378
+
379
+ # Set the gradient fill properties for the labels.
380
+ gradient = gradient_properties(property[:gradient])
381
+
382
+ # Pattern fill overrides solid fill.
383
+ if pattern
384
+ fill = nil
385
+ end
386
+
387
+ # Gradient fill overrides solid and pattern fills.
388
+ if gradient
389
+ pattern = nil
390
+ fill = nil
391
+ end
392
+
393
+ property[:line] = line
394
+ property[:fill] = fill
395
+ property[:pattern] = pattern
396
+ property[:gradient] = gradient
397
+
398
+ custom << property
399
+ end
400
+ labels[:custom] = custom
401
+ end
402
+
303
403
  labels
304
404
  end
305
405
  end
@@ -804,9 +804,9 @@ def params_to_font(params)
804
804
  #
805
805
  # Write the <c:txPr> element.
806
806
  #
807
- def write_tx_pr(is_y_axis, font) # :nodoc:
807
+ def write_tx_pr(font, is_y_axis = nil) # :nodoc:
808
808
  rotation = nil
809
- if font && font[:_rotation]
809
+ if font && font.respond_to?(:[]) && font[:_rotation]
810
810
  rotation = font[:_rotation]
811
811
  end
812
812
  @writer.tag_elements('c:txPr') do
@@ -903,6 +903,7 @@ def write_def_rpr_r_pr_common(font, style_attributes, tag) # :nodoc:
903
903
  #
904
904
  def get_font_latin_attributes(font)
905
905
  return [] unless font
906
+ return [] unless font.respond_to?(:[])
906
907
 
907
908
  attributes = []
908
909
  attributes << ['typeface', font[:_name]] if ptrue?(font[:_name])
@@ -959,6 +960,7 @@ def color(color_code) # :nodoc:
959
960
  #
960
961
  def get_font_style_attributes(font)
961
962
  return [] unless font
963
+ return [] unless font.respond_to?(:[])
962
964
 
963
965
  attributes = []
964
966
  attributes << ['sz', font[:_size]] if ptrue?(font[:_size])
@@ -1 +1 @@
1
- WriteXLSX_VERSION = "1.04.0"
1
+ WriteXLSX_VERSION = "1.07.0"
@@ -2514,7 +2514,9 @@ def write_array_formula(*args)
2514
2514
  col1, col2 = col2, col1 if col1 > col2
2515
2515
 
2516
2516
  # Check that row and col are valid and store max and min values
2517
+ check_dimensions(row1, col1)
2517
2518
  check_dimensions(row2, col2)
2519
+ store_row_col_max_min_values(row1, col1)
2518
2520
  store_row_col_max_min_values(row2, col2)
2519
2521
 
2520
2522
  # Define array range
@@ -3363,9 +3365,11 @@ def merge_range(*args)
3363
3365
  row_first, row_last = row_last, row_first if row_first > row_last
3364
3366
  col_first, col_last = col_last, col_first if col_first > col_last
3365
3367
 
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)
3368
+ # Check that the data range is valid and store the max and min values.
3369
+ check_dimensions(row_first, col_first)
3370
+ check_dimensions(row_last, col_last)
3371
+ store_row_col_max_min_values(row_first, col_first)
3372
+ store_row_col_max_min_values(row_last, col_last)
3369
3373
 
3370
3374
  # Store the merge range.
3371
3375
  @merge << [row_first, col_first, row_last, col_last]
@@ -3428,9 +3432,11 @@ def merge_range_type(type, *args)
3428
3432
  row_first, row_last = row_last, row_first if row_first > row_last
3429
3433
  col_first, col_last = col_last, col_first if col_first > col_last
3430
3434
 
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)
3435
+ # Check that the data range is valid and store the max and min values.
3436
+ check_dimensions(row_first, col_first)
3437
+ check_dimensions(row_last, col_last)
3438
+ store_row_col_max_min_values(row_first, col_first)
3439
+ store_row_col_max_min_values(row_last, col_last)
3434
3440
 
3435
3441
  # Store the merge range.
3436
3442
  @merge << [row_first, col_first, row_last, col_last]
@@ -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
@@ -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
@@ -0,0 +1,52 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ class TestRegressionChartDataLabels28 < 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_labels28
14
+ @xlsx = 'chart_data_labels28.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
+ ['foo', 'bar']
27
+ ]
28
+
29
+ worksheet.write('A1', data)
30
+
31
+ custom = [
32
+ {:value => 123},
33
+ {:value => 'abc'},
34
+ nil,
35
+ {:formula => 'Sheet1!$D$1'},
36
+ {:formula => 'Sheet1!$D$2'}
37
+ ]
38
+
39
+ chart.add_series(
40
+ :values => '=Sheet1!$A$1:$A$5',
41
+ :data_labels => {:value => 1, :custom => custom }
42
+ )
43
+
44
+ chart.add_series(:values => '=Sheet1!$B$1:$B$5')
45
+ chart.add_series(:values => '=Sheet1!$C$1:$C$5')
46
+
47
+ worksheet.insert_chart('E9', chart)
48
+
49
+ workbook.close
50
+ compare_for_regression
51
+ end
52
+ end
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ class TestRegressionChartDataLabels29 < 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_labels29
14
+ @xlsx = 'chart_data_labels29.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, [67858816, 67863296])
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(
31
+ :values => '=Sheet1!$A$1:$A$5',
32
+ :data_labels => {:value => 1, :custom => [{:delete => 1}] }
33
+ )
34
+
35
+ chart.add_series(:values => '=Sheet1!$B$1:$B$5')
36
+ chart.add_series(:values => '=Sheet1!$C$1:$C$5')
37
+
38
+ worksheet.insert_chart('E9', chart)
39
+
40
+ workbook.close
41
+ compare_for_regression
42
+ end
43
+ end
@@ -0,0 +1,46 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'helper'
3
+
4
+ class TestRegressionChartDataLabels30 < 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_labels30
14
+ @xlsx = 'chart_data_labels30.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, [67858816, 67863296])
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(
31
+ :values => '=Sheet1!$A$1:$A$5',
32
+ :data_labels => {
33
+ :value => 1,
34
+ :custom => [{:delete => 1}, nil, {:delete => 1}, nil, {:delete => 1}]
35
+ }
36
+ )
37
+
38
+ chart.add_series(:values => '=Sheet1!$B$1:$B$5')
39
+ chart.add_series(:values => '=Sheet1!$C$1:$C$5')
40
+
41
+ worksheet.insert_chart('E9', chart)
42
+
43
+ workbook.close
44
+ compare_for_regression
45
+ end
46
+ end