write_xlsx 0.62.0 → 0.64.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. data/README.rdoc +14 -1
  2. data/examples/chart_data_tools.rb +215 -0
  3. data/examples/chart_pie.rb +36 -5
  4. data/examples/sparklines2.rb +1 -1
  5. data/examples/tab_colors.rb +3 -3
  6. data/lib/write_xlsx/chart.rb +559 -516
  7. data/lib/write_xlsx/chart/area.rb +4 -1
  8. data/lib/write_xlsx/chart/axis.rb +132 -0
  9. data/lib/write_xlsx/chart/bar.rb +17 -9
  10. data/lib/write_xlsx/chart/column.rb +9 -1
  11. data/lib/write_xlsx/chart/line.rb +24 -0
  12. data/lib/write_xlsx/chart/radar.rb +2 -2
  13. data/lib/write_xlsx/chart/scatter.rb +19 -0
  14. data/lib/write_xlsx/chart/stock.rb +10 -3
  15. data/lib/write_xlsx/drawing.rb +43 -44
  16. data/lib/write_xlsx/package/vml.rb +21 -14
  17. data/lib/write_xlsx/shape.rb +173 -22
  18. data/lib/write_xlsx/sparkline.rb +524 -0
  19. data/lib/write_xlsx/version.rb +1 -1
  20. data/lib/write_xlsx/workbook.rb +183 -115
  21. data/lib/write_xlsx/worksheet.rb +821 -1073
  22. data/lib/write_xlsx/worksheet/cell_data.rb +132 -0
  23. data/lib/write_xlsx/worksheet/print_style.rb +51 -0
  24. data/test/chart/test_add_series.rb +31 -6
  25. data/test/chart/test_write_d_lbls.rb +18 -18
  26. data/test/chart/test_write_number_format.rb +20 -24
  27. data/test/drawing/test_drawing_shape_01.rb +1 -1
  28. data/test/drawing/test_drawing_shape_02.rb +2 -2
  29. data/test/drawing/test_drawing_shape_03.rb +5 -5
  30. data/test/drawing/test_drawing_shape_04.rb +3 -3
  31. data/test/drawing/test_drawing_shape_05.rb +4 -4
  32. data/test/drawing/test_drawing_shape_07.rb +2 -2
  33. data/test/perl_output/chart_data_tools.xlsx +0 -0
  34. data/test/perl_output/chart_pie.xlsx +0 -0
  35. data/test/regression/disabled_test_vml04.rb +2 -2
  36. data/test/regression/test_chart_drop_lines01.rb +46 -0
  37. data/test/regression/test_chart_drop_lines02.rb +51 -0
  38. data/test/regression/test_chart_drop_lines03.rb +46 -0
  39. data/test/regression/test_chart_drop_lines04.rb +64 -0
  40. data/test/regression/test_chart_errorbars01.rb +47 -0
  41. data/test/regression/test_chart_errorbars02.rb +57 -0
  42. data/test/regression/test_chart_errorbars03.rb +53 -0
  43. data/test/regression/test_chart_errorbars04.rb +48 -0
  44. data/test/regression/test_chart_errorbars05.rb +47 -0
  45. data/test/regression/test_chart_errorbars06.rb +47 -0
  46. data/test/regression/test_chart_errorbars07.rb +66 -0
  47. data/test/regression/test_chart_font02.rb +1 -1
  48. data/test/regression/test_chart_font06.rb +1 -1
  49. data/test/regression/test_chart_gridlines04.rb +2 -1
  50. data/test/regression/test_chart_gridlines08.rb +2 -1
  51. data/test/regression/test_chart_points01.rb +37 -0
  52. data/test/regression/test_chart_points02.rb +40 -0
  53. data/test/regression/test_chart_points03.rb +42 -0
  54. data/test/regression/test_chart_points04.rb +52 -0
  55. data/test/regression/test_chart_points05.rb +49 -0
  56. data/test/regression/test_chart_points06.rb +49 -0
  57. data/test/regression/test_chartsheet05.rb +1 -1
  58. data/test/regression/test_chartsheet06.rb +1 -1
  59. data/test/regression/test_comment01.rb +1 -1
  60. data/test/regression/test_comment02.rb +1 -1
  61. data/test/regression/test_comment03.rb +1 -1
  62. data/test/regression/test_comment04.rb +2 -2
  63. data/test/regression/test_comment06.rb +1 -1
  64. data/test/regression/test_comment07.rb +1 -1
  65. data/test/regression/test_comment08.rb +1 -1
  66. data/test/regression/test_comment09.rb +1 -1
  67. data/test/regression/test_comment10.rb +1 -1
  68. data/test/regression/test_default_row04.rb +1 -1
  69. data/test/regression/test_escapes02.rb +1 -1
  70. data/test/regression/test_hyperlink15.rb +2 -2
  71. data/test/regression/test_shape_connect01.rb +6 -6
  72. data/test/regression/test_shape_connect02.rb +6 -6
  73. data/test/regression/test_shape_connect03.rb +11 -11
  74. data/test/regression/test_shape_connect04.rb +10 -10
  75. data/test/regression/test_shape_scale01.rb +2 -2
  76. data/test/regression/test_shape_stencil01.rb +3 -3
  77. data/test/regression/test_tab_color01.rb +1 -1
  78. data/test/regression/test_table04.rb +1 -1
  79. data/test/regression/test_table05.rb +1 -1
  80. data/test/regression/test_table06.rb +1 -1
  81. data/test/regression/test_vml01.rb +1 -1
  82. data/test/regression/test_vml02.rb +1 -1
  83. data/test/regression/test_vml03.rb +2 -2
  84. data/test/regression/xlsx_files/chart_drop_lines01.xlsx +0 -0
  85. data/test/regression/xlsx_files/chart_drop_lines02.xlsx +0 -0
  86. data/test/regression/xlsx_files/chart_drop_lines03.xlsx +0 -0
  87. data/test/regression/xlsx_files/chart_drop_lines04.xlsx +0 -0
  88. data/test/regression/xlsx_files/chart_errorbars01.xlsx +0 -0
  89. data/test/regression/xlsx_files/chart_errorbars02.xlsx +0 -0
  90. data/test/regression/xlsx_files/chart_errorbars03.xlsx +0 -0
  91. data/test/regression/xlsx_files/chart_errorbars04.xlsx +0 -0
  92. data/test/regression/xlsx_files/chart_errorbars05.xlsx +0 -0
  93. data/test/regression/xlsx_files/chart_errorbars06.xlsx +0 -0
  94. data/test/regression/xlsx_files/chart_errorbars07.xlsx +0 -0
  95. data/test/regression/xlsx_files/chart_points01.xlsx +0 -0
  96. data/test/regression/xlsx_files/chart_points02.xlsx +0 -0
  97. data/test/regression/xlsx_files/chart_points03.xlsx +0 -0
  98. data/test/regression/xlsx_files/chart_points04.xlsx +0 -0
  99. data/test/regression/xlsx_files/chart_points05.xlsx +0 -0
  100. data/test/regression/xlsx_files/chart_points06.xlsx +0 -0
  101. data/test/regression/xlsx_files/chart_stock02.xlsx +0 -0
  102. data/test/test_example_match.rb +278 -57
  103. data/test/worksheet/test_convert_date_time_02.rb +427 -433
  104. data/test/worksheet/test_convert_date_time_03.rb +1 -1
  105. data/test/worksheet/test_write_sheet_pr.rb +2 -2
  106. data/test/worksheet/test_write_sheet_view1.rb +2 -2
  107. metadata +80 -10
@@ -28,7 +28,7 @@ def initialize(subtype)
28
28
 
29
29
  # Override and reset the default axis values.
30
30
  if @subtype == 'percent_stacked'
31
- @y_axis[:_defaults][:num_format] = '0%'
31
+ @y_axis.defaults[:num_format] = '0%'
32
32
  end
33
33
 
34
34
  set_y_axis
@@ -60,6 +60,9 @@ def write_area_chart(params)
60
60
  # Write the series elements.
61
61
  series.each {|s| write_series(s)}
62
62
 
63
+ # Write the c:dropLines element.
64
+ write_drop_lines
65
+
63
66
  # Write the c:marker element.
64
67
  write_marker_value
65
68
 
@@ -0,0 +1,132 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'write_xlsx/package/xml_writer_simple'
3
+ require 'write_xlsx/utility'
4
+
5
+ module Writexlsx
6
+ class Chart
7
+ class Axis
8
+ include Writexlsx::Utility
9
+
10
+ attr_accessor :defaults, :name, :formula, :data_id, :reverse
11
+ attr_accessor :min, :max
12
+ attr_accessor :minor_unit, :major_unit, :minor_unit_type, :major_unit_type
13
+ attr_accessor :log_base, :crossing, :position, :label_position, :visible
14
+ attr_accessor :num_format, :num_format_linked, :num_font, :name_font
15
+ attr_accessor :major_gridlines, :minor_gridlines, :major_tick_mark
16
+
17
+ #
18
+ # Convert user defined axis values into axis instance.
19
+ #
20
+ def merge_with_hash(chart, params) # :nodoc:
21
+ @chart = chart
22
+ args = (defaults || {}).merge(params)
23
+
24
+ @name, @formula = @chart.process_names(args[:name], args[:name_formula])
25
+ @data_id = @chart.get_data_id(@formula, args[:data])
26
+ @reverse = args[:reverse]
27
+ @min = args[:min]
28
+ @max = args[:max]
29
+ @minor_unit = args[:minor_unit]
30
+ @major_unit = args[:major_unit]
31
+ @minor_unit_type = args[:minor_unit_type]
32
+ @major_unit_type = args[:major_unit_type]
33
+ @log_base = args[:log_base]
34
+ @crossing = args[:crossing]
35
+ @label_position = args[:label_position]
36
+ @num_format = args[:num_format]
37
+ @num_format_linked = args[:num_format_linked]
38
+ @visible = args[:visible] || 1
39
+
40
+ # Map major/minor_gridlines properties.
41
+ [:major_gridlines, :minor_gridlines].each do |lines|
42
+ if args[lines] && ptrue?(args[lines][:visible])
43
+ instance_variable_set("@#{lines}", gridline_properties(args[lines]))
44
+ else
45
+ instance_variable_set("@#{lines}", nil)
46
+ end
47
+ end
48
+ @major_tick_mark = args[:major_tick_mark]
49
+
50
+ # Only use the first letter of bottom, top, left or right.
51
+ @position = args[:position]
52
+ @position = @position.downcase[0, 1] if @position
53
+
54
+ # Set the font properties if present.
55
+ @num_font = @chart.convert_font_args(args[:num_font])
56
+ @name_font = @chart.convert_font_args(args[:name_font])
57
+ end
58
+
59
+ #
60
+ # Write the <c:numberFormat> element. Note: It is assumed that if a user
61
+ # defined number format is supplied (i.e., non-default) then the sourceLinked
62
+ # attribute is 0. The user can override this if required.
63
+ #
64
+
65
+ def write_number_format(writer) # :nodoc:
66
+ source_linked = 1
67
+
68
+ # Check if a user defined number format has been set.
69
+ if @defaults && @num_format != @defaults[:num_format]
70
+ source_linked = 0
71
+ end
72
+
73
+ # User override of sourceLinked.
74
+ if ptrue?(@num_format_linked)
75
+ source_linked = 1
76
+ end
77
+
78
+ attributes = [
79
+ 'formatCode', @num_format,
80
+ 'sourceLinked', source_linked
81
+ ]
82
+
83
+ writer.empty_tag('c:numFmt', attributes)
84
+ end
85
+
86
+ #
87
+ # Write the <c:numFmt> element. Special case handler for category axes which
88
+ # don't always have a number format.
89
+ #
90
+ def write_cat_number_format(writer, cat_has_num_fmt)
91
+ source_linked = 1
92
+ default_format = true
93
+
94
+ # Check if a user defined number format has been set.
95
+ if @defaults && @num_format != @defaults[:num_format]
96
+ source_linked = 0
97
+ default_format = false
98
+ end
99
+
100
+ # User override of linkedSource.
101
+ if @num_format_linked
102
+ source_linked = 1
103
+ end
104
+
105
+ # Skip if cat doesn't have a num format (unless it is non-default).
106
+ if !cat_has_num_fmt && default_format
107
+ return ''
108
+ end
109
+
110
+ attributes = [
111
+ 'formatCode', @num_format,
112
+ 'sourceLinked', source_linked,
113
+ ]
114
+
115
+ writer.empty_tag('c:numFmt', attributes)
116
+ end
117
+
118
+ #
119
+ # Convert user defined gridline properties to the structure required internally.
120
+ #
121
+ def gridline_properties(args)
122
+ # Set the visible property for the gridline.
123
+ gridline = { :_visible => args[:visible] }
124
+
125
+ # Set the line properties for the gridline.
126
+ gridline[:_line] = @chart.line_properties(args[:line])
127
+
128
+ gridline
129
+ end
130
+ end
131
+ end
132
+ end
@@ -29,19 +29,19 @@ def initialize(subtype)
29
29
  @show_crosses = false
30
30
 
31
31
  # Override and reset the default axis values.
32
- if @x_axis[:_defaults]
33
- @x_axis[:_defaults][:major_gridlines] = { :visible => 1 }
32
+ if @x_axis.defaults
33
+ @x_axis.defaults[:major_gridlines] = { :visible => 1 }
34
34
  else
35
- @x_axis[:_defaults] = { :major_gridlines => { :visible => 1 } }
35
+ @x_axis.defaults = { :major_gridlines => { :visible => 1 } }
36
36
  end
37
- if @y_axis[:_defaults]
38
- @y_axis[:_defaults][:major_gridlines] = { :visible => 0 }
37
+ if @y_axis.defaults
38
+ @y_axis.defaults[:major_gridlines] = { :visible => 0 }
39
39
  else
40
- @y_axis[:_defaults] = { :major_gridlines => { :visible => 0 } }
40
+ @y_axis.defaults = { :major_gridlines => { :visible => 0 } }
41
41
  end
42
42
 
43
43
  if @subtype == 'percent_stacked'
44
- @x_axis[:_defaults][:num_format] = '0%'
44
+ @x_axis.defaults[:num_format] = '0%'
45
45
  end
46
46
 
47
47
  set_x_axis
@@ -55,8 +55,8 @@ def write_chart_type(params)
55
55
  if params[:primary_axes] != 0
56
56
  # Reverse X and Y axes for Bar charts.
57
57
  @y_axis, @x_axis = @x_axis, @y_axis
58
- if @y2_axis[:_position] == 'r'
59
- @y2_axis[:_position] = 't'
58
+ if @y2_axis.position == 'r'
59
+ @y2_axis.position = 't'
60
60
  end
61
61
  end
62
62
 
@@ -74,6 +74,14 @@ def write_bar_dir
74
74
 
75
75
  @writer.empty_tag('c:barDir', attributes)
76
76
  end
77
+
78
+ #
79
+ # Write the <c:errDir> element. Overridden from Chart class since it is not
80
+ # used in Bar charts.
81
+ #
82
+ def write_err_dir(direction)
83
+ # do nothing
84
+ end
77
85
  end
78
86
  end
79
87
  end
@@ -35,7 +35,7 @@ def initialize(subtype)
35
35
 
36
36
  # Override and reset the default axis values.
37
37
  if @subtype == 'percent_stacked'
38
- @y_axis[:_defaults][:num_format] = '0%'
38
+ @y_axis.defaults[:num_format] = '0%'
39
39
  end
40
40
 
41
41
  set_y_axis
@@ -59,6 +59,14 @@ def write_bar_dir
59
59
 
60
60
  @writer.empty_tag('c:barDir', attributes)
61
61
  end
62
+
63
+ #
64
+ # Write the <c:errDir> element. Overridden from Chart class since it is not
65
+ # used in Bar charts.
66
+ #
67
+ def write_err_dir(direction)
68
+ # do nothing
69
+ end
62
70
  end
63
71
  end
64
72
  end
@@ -45,6 +45,15 @@ def write_line_chart(params)
45
45
  # Write the series elements.
46
46
  series.each {|s| write_series(s)}
47
47
 
48
+ # Write the c:dropLines element.
49
+ write_drop_lines
50
+
51
+ # Write the c:hiLowLines element.
52
+ write_hi_low_lines
53
+
54
+ # Write the c:upDownBars element.
55
+ write_up_down_bars
56
+
48
57
  # Write the c:marker element.
49
58
  write_marker_value
50
59
 
@@ -52,6 +61,21 @@ def write_line_chart(params)
52
61
  write_axis_ids(params)
53
62
  end
54
63
  end
64
+
65
+ #
66
+ # Write an individual <c:dPt> element. Override the parent method to add
67
+ # markers.
68
+ #
69
+ def write_d_pt_point(index, point)
70
+ @writer.tag_elements('c:dPt') do
71
+ # Write the c:idx element.
72
+ write_idx(index)
73
+ @writer.tag_elements('c:marker') do
74
+ # Write the c:spPr element.
75
+ write_sp_pr(point)
76
+ end
77
+ end
78
+ end
55
79
  end
56
80
  end
57
81
  end
@@ -36,11 +36,11 @@ def initialize(subtype)
36
36
  end
37
37
 
38
38
  # Override and reset the default axis values.
39
- @x_axis[:_defaults][:major_gridlines] = { :visible => 1 }
39
+ @x_axis.defaults[:major_gridlines] = { :visible => 1 }
40
40
  set_x_axis
41
41
 
42
42
  # Hardcode major_tick_mark for now untill there is an accessor.
43
- @y_axis[:_major_tick_mark] = 'cross'
43
+ @y_axis.major_tick_mark = 'cross'
44
44
  end
45
45
 
46
46
  #
@@ -110,10 +110,14 @@ def write_ser(series)
110
110
  write_sp_pr(series)
111
111
  # Write the c:marker element.
112
112
  write_marker(series[:_marker])
113
+ # Write the c:dPt element.
114
+ write_d_pt(series[:_points])
113
115
  # Write the c:dLbls element.
114
116
  write_d_lbls(series[:_labels])
115
117
  # Write the c:trendline element.
116
118
  write_trendline(series[:_trendline])
119
+ # Write the c:errBars element.
120
+ write_error_bars(series[:_error_bars])
117
121
  # Write the c:xVal element.
118
122
  write_x_val(series)
119
123
  # Write the c:yVal element.
@@ -266,6 +270,21 @@ def modify_series_formatting
266
270
  end
267
271
  end
268
272
  end
273
+
274
+ #
275
+ # Write an individual <c:dPt> element. Override the parent method to add
276
+ # markers.
277
+ #
278
+ def write_d_pt_point(index, point)
279
+ @writer.tag_elements('c:dPt') do
280
+ # Write the c:idx element.
281
+ write_idx(index)
282
+ @writer.tag_elements('c:marker') do
283
+ # Write the c:spPr element.
284
+ write_sp_pr(point)
285
+ end
286
+ end
287
+ end
269
288
  end
270
289
  end
271
290
  end
@@ -27,10 +27,11 @@ class Stock < self
27
27
  def initialize(subtype)
28
28
  super(subtype)
29
29
  @show_crosses = false
30
+ @hi_low_lines = {}
30
31
 
31
32
  # Override and reset the default axis values.
32
- @x_axis[:_defaults][:num_format] = 'dd/mm/yyyy'
33
- @x2_axis[:_defaults][:num_format] = 'dd/mm/yyyy'
33
+ @x_axis.defaults[:num_format] = 'dd/mm/yyyy'
34
+ @x2_axis.defaults[:num_format] = 'dd/mm/yyyy'
34
35
  set_x_axis
35
36
  set_x2_axis
36
37
  end
@@ -62,8 +63,14 @@ def write_stock_chart(params)
62
63
  # Write the series elements.
63
64
  series.each {|s| write_series(s)}
64
65
 
66
+ # Write the c:dtopLines element.
67
+ write_drop_lines
68
+
65
69
  # Write the c:hiLowLines element.
66
- write_hi_low_lines if params[:primary_axes] == 1
70
+ write_hi_low_lines if ptrue?(params[:primary_axes])
71
+
72
+ # Write the c:upDownBars element.
73
+ write_up_down_bars
67
74
 
68
75
  # Write the c:marker element.
69
76
  write_marker_value
@@ -89,7 +89,7 @@ def write_two_cell_anchor(*args)
89
89
  attributes << :editAs << 'oneCell' if type == 2
90
90
 
91
91
  # Add attribute for shapes.
92
- attributes << :editAs << shape[:edit_as] if shape && !shape[:edit_as].nil?
92
+ attributes << :editAs << shape.edit_as if shape && !shape.edit_as.nil?
93
93
 
94
94
  @writer.tag_elements('xdr:twoCellAnchor', attributes) do
95
95
  # Write the xdr:from element.
@@ -400,7 +400,7 @@ def write_client_data
400
400
  # Write the <xdr:sp> element.
401
401
  #
402
402
  def write_sp(index, col_absolute, row_absolute, width, height, shape)
403
- if shape[:connect] != 0
403
+ if shape.connect != 0
404
404
  attributes = [:macro, '']
405
405
  @writer.tag_elements('xdr:cxnSp', attributes) do
406
406
 
@@ -422,7 +422,7 @@ def write_sp(index, col_absolute, row_absolute, width, height, shape)
422
422
  write_xdr_sp_pr(index, col_absolute, row_absolute, width, height, shape)
423
423
 
424
424
  # Write the xdr:txBody element.
425
- if shape[:text] != 0
425
+ if shape.text != 0
426
426
  write_txBody(col_absolute, row_absolute, width, height, shape)
427
427
  end
428
428
  end
@@ -435,21 +435,21 @@ def write_sp(index, col_absolute, row_absolute, width, height, shape)
435
435
  def write_nv_cxn_sp_pr(index, shape)
436
436
  @writer.tag_elements('xdr:nvCxnSpPr') do
437
437
 
438
- shape[:name] = [shape[:type], index].join(' ') unless shape[:name]
439
- write_c_nv_pr(shape[:id], shape[:name])
438
+ shape.name = [shape.type, index].join(' ') unless shape.name
439
+ write_c_nv_pr(shape.id, shape.name)
440
440
 
441
441
  @writer.tag_elements('xdr:cNvCxnSpPr') do
442
442
 
443
443
  attributes = [:noChangeShapeType, '1']
444
444
  @writer.empty_tag('a:cxnSpLocks', attributes)
445
445
 
446
- if shape[:start]
447
- attributes = ['id', shape[:start], 'idx', shape[:start_index]]
446
+ if shape.start
447
+ attributes = ['id', shape.start, 'idx', shape.start_index]
448
448
  @writer.empty_tag('a:stCxn', attributes)
449
449
  end
450
450
 
451
- if shape[:end]
452
- attributes = ['id', shape[:end], 'idx', shape[:end_index]]
451
+ if shape.end
452
+ attributes = ['id', shape.end, 'idx', shape.end_index]
453
453
  @writer.empty_tag('a:endCxn', attributes)
454
454
  end
455
455
  end
@@ -461,14 +461,13 @@ def write_nv_cxn_sp_pr(index, shape)
461
461
  #
462
462
  def write_nv_sp_pr(index, shape)
463
463
  attributes = []
464
+ attributes << 'txBox' << 1 if shape.tx_box
464
465
 
465
466
  @writer.tag_elements('xdr:nvSpPr') do
466
- shape_name = "#{shape[:type]} #{index}"
467
- write_c_nv_pr(shape[:id], shape_name)
468
- attributes = ['txBox', 1] if shape[:tx_box] != 0
467
+ write_c_nv_pr(shape.id, "#{shape.type} #{index}")
468
+
469
469
  @writer.tag_elements('xdr:cNvSpPr', attributes) do
470
- attributes = [:noChangeArrowheads, '1']
471
- @writer.empty_tag('a:spLocks', attributes)
470
+ @writer.empty_tag('a:spLocks', [:noChangeArrowheads, '1'])
472
471
  end
473
472
  end
474
473
  end
@@ -485,7 +484,7 @@ def write_pic(index, col_absolute, row_absolute, width, height, description)
485
484
 
486
485
  # Pictures are rectangle shapes by default.
487
486
  shape = Shape.new
488
- shape[:type] = 'rect'
487
+ shape.type = 'rect'
489
488
 
490
489
  # Write the xdr:spPr element.
491
490
  write_sp_pr(col_absolute, row_absolute, width, height, shape)
@@ -596,9 +595,9 @@ def write_xdr_sp_pr(index, col_absolute, row_absolute, width, height, shape)
596
595
  # Write the a:prstGeom element.
597
596
  write_a_prst_geom(shape)
598
597
 
599
- if shape[:fill].to_s.bytesize > 1
598
+ if shape.fill.to_s.bytesize > 1
600
599
  # Write the a:solidFill element.
601
- write_a_solid_fill(shape[:fill])
600
+ write_a_solid_fill(shape.fill)
602
601
  else
603
602
  @writer.empty_tag('a:noFill')
604
603
  end
@@ -611,15 +610,15 @@ def write_xdr_sp_pr(index, col_absolute, row_absolute, width, height, shape)
611
610
  #
612
611
  # Write the <a:xfrm> element.
613
612
  #
614
- def write_a_xfrm(col_absolute, row_absolute, width, height, shape = {})
613
+ def write_a_xfrm(col_absolute, row_absolute, width, height, shape = nil)
615
614
  attributes = []
616
615
 
617
- rotation = shape[:rotation] || 0
616
+ rotation = shape ? shape.rotation : 0
618
617
  rotation *= 60000
619
618
 
620
619
  attributes << 'rot' << rotation if rotation != 0
621
- attributes << 'flipH' << 1 if ptrue?(shape[:flip_h])
622
- attributes << 'flipV' << 1 if ptrue?(shape[:flip_v])
620
+ attributes << 'flipH' << 1 if shape && ptrue?(shape.flip_h)
621
+ attributes << 'flipV' << 1 if shape && ptrue?(shape.flip_v)
623
622
 
624
623
  @writer.tag_elements('a:xfrm', attributes) do
625
624
  # Write the a:off element.
@@ -659,7 +658,7 @@ def write_a_ext(cx, cy)
659
658
  #
660
659
  def write_a_prst_geom(shape = {})
661
660
  attributes = []
662
- attributes << 'prst' << shape[:type] if shape[:type]
661
+ attributes << 'prst' << shape.type if shape.type
663
662
 
664
663
  @writer.tag_elements('a:prstGeom', attributes) do
665
664
  # Write the a:avLst element.
@@ -671,11 +670,11 @@ def write_a_prst_geom(shape = {})
671
670
  # Write the <a:avLst> element.
672
671
  #
673
672
  def write_a_av_lst(shape = {})
674
- if shape[:adjustments].respond_to?(:empty?)
675
- adjustments = shape[:adjustments]
676
- elsif shape[:adjustments].respond_to?(:coerce)
677
- adjustments = [shape[:adjustments]]
678
- elsif !shape[:adjustments]
673
+ if shape.adjustments.respond_to?(:empty?)
674
+ adjustments = shape.adjustments
675
+ elsif shape.adjustments.respond_to?(:coerce)
676
+ adjustments = [shape.adjustments]
677
+ elsif !shape.adjustments
679
678
  adjustments = []
680
679
  end
681
680
 
@@ -685,7 +684,7 @@ def write_a_av_lst(shape = {})
685
684
  adjustments.each do |adj|
686
685
  i += 1
687
686
  # Only connectors have multiple adjustments.
688
- suffix = shape[:connect] != 0 ? i : ''
687
+ suffix = shape.connect != 0 ? i : ''
689
688
 
690
689
  # Scale Adjustments: 100,000 = 100%.
691
690
  adj_int = (adj * 1000).to_i
@@ -714,10 +713,10 @@ def write_a_solid_fill(rgb = '000000')
714
713
  # Write the <a:ln> elements.
715
714
  #
716
715
  def write_a_ln(shape = {})
717
- weight = shape[:line_weight] || 0
716
+ weight = shape.line_weight || 0
718
717
  attributes = ['w', weight * 9525]
719
718
  @writer.tag_elements('a:ln', attributes) do
720
- line = shape[:line] || 0
719
+ line = shape.line || 0
721
720
  if line.to_s.bytesize > 1
722
721
  # Write the a:solidFill element.
723
722
  write_a_solid_fill(line)
@@ -725,12 +724,12 @@ def write_a_ln(shape = {})
725
724
  @writer.empty_tag('a:noFill')
726
725
  end
727
726
 
728
- if shape[:line_type] != ''
729
- attributes = ['val', shape[:line_type]]
727
+ if shape.line_type != ''
728
+ attributes = ['val', shape.line_type]
730
729
  @writer.empty_tag('a:prstDash', attributes)
731
730
  end
732
731
 
733
- if shape[:connect] != 0
732
+ if shape.connect != 0
734
733
  @writer.empty_tag('a:round')
735
734
  else
736
735
  attributes = ['lim', 800000]
@@ -753,7 +752,7 @@ def write_txBody(col_absolute, row_absolute, width, height, shape)
753
752
  :tIns, "22860",
754
753
  :rIns, "27432",
755
754
  :bIns, "22860",
756
- :anchor, shape[:valign],
755
+ :anchor, shape.valign,
757
756
  :upright, "1"
758
757
  ]
759
758
  @writer.tag_elements('xdr:txBody') do
@@ -761,23 +760,23 @@ def write_txBody(col_absolute, row_absolute, width, height, shape)
761
760
  @writer.empty_tag('a:lstStyle')
762
761
 
763
762
  @writer.tag_elements('a:p') do
764
- rotation = shape[:format][:rotation] || 0
763
+ rotation = shape.format[:rotation] || 0
765
764
  rotation *= 60000
766
765
 
767
- attributes = [:algn, shape[:align], :rtl, rotation]
766
+ attributes = [:algn, shape.align, :rtl, rotation]
768
767
  @writer.tag_elements('a:pPr', attributes) do
769
768
  attributes = [:sz, "1000"]
770
769
  @writer.empty_tag('a:defRPr', attributes)
771
770
  end
772
771
 
773
772
  @writer.tag_elements('a:r') do
774
- size = shape[:format][:size] || 8
773
+ size = shape.format[:size] || 8
775
774
  size *= 100
776
775
 
777
- bold = shape[:format][:bold] || 0
778
- italic = shape[:format][:italic] || 0
779
- underline = ptrue?(shape[:format][:underline]) ? 'sng' : 'none'
780
- strike = ptrue?(shape[:format][:font_strikeout]) ? 'Strike' : 'noStrike'
776
+ bold = shape.format[:bold] || 0
777
+ italic = shape.format[:italic] || 0
778
+ underline = ptrue?(shape.format[:underline]) ? 'sng' : 'none'
779
+ strike = ptrue?(shape.format[:font_strikeout]) ? 'Strike' : 'noStrike'
781
780
 
782
781
  attributes = [
783
782
  :lang, "en-US",
@@ -789,7 +788,7 @@ def write_txBody(col_absolute, row_absolute, width, height, shape)
789
788
  :baseline, 0
790
789
  ]
791
790
  @writer.tag_elements('a:rPr', attributes) do
792
- color = shape[:format][:color]
791
+ color = shape.format[:color]
793
792
  if color
794
793
  color = shape.get_palette_color(color)
795
794
  color = color.sub(/^FF/, '') # Remove leading FF from rgb for shape color.
@@ -799,13 +798,13 @@ def write_txBody(col_absolute, row_absolute, width, height, shape)
799
798
 
800
799
  write_a_solid_fill(color)
801
800
 
802
- font = shape[:format][:font] || 'Calibri'
801
+ font = shape.format[:font] || 'Calibri'
803
802
  attributes = [:typeface, font]
804
803
  @writer.empty_tag('a:latin', attributes)
805
804
  @writer.empty_tag('a:cs', attributes)
806
805
  end
807
806
  @writer.tag_elements('a:t') do
808
- @writer.characters(shape[:text])
807
+ @writer.characters(shape.text)
809
808
  end
810
809
  end
811
810
  end