write_xlsx 0.51.0 → 0.54.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.
Files changed (160) hide show
  1. data/.gitignore +39 -0
  2. data/Gemfile +4 -14
  3. data/LICENSE.txt +3 -1
  4. data/README.rdoc +5 -0
  5. data/Rakefile +4 -71
  6. data/examples/chart_radar.rb +127 -0
  7. data/examples/chart_secondary_axis.rb +1 -1
  8. data/lib/write_xlsx/chart/area.rb +7 -18
  9. data/lib/write_xlsx/chart/bar.rb +20 -23
  10. data/lib/write_xlsx/chart/column.rb +7 -20
  11. data/lib/write_xlsx/chart/radar.rb +94 -0
  12. data/lib/write_xlsx/chart/stock.rb +6 -0
  13. data/lib/write_xlsx/chart.rb +317 -116
  14. data/lib/write_xlsx/package/xml_writer_simple.rb +2 -2
  15. data/lib/write_xlsx/version.rb +5 -0
  16. data/test/chart/test_write_a_latin.rb +22 -0
  17. data/test/chart/test_write_auto.rb +1 -1
  18. data/test/chart/test_write_ax_id.rb +1 -1
  19. data/test/chart/test_write_ax_pos.rb +1 -1
  20. data/test/chart/test_write_cross_ax.rb +1 -1
  21. data/test/chart/test_write_crosses.rb +1 -1
  22. data/test/chart/test_write_d_lbls.rb +18 -18
  23. data/test/chart/test_write_idx.rb +1 -1
  24. data/test/chart/test_write_label_align.rb +1 -1
  25. data/test/chart/test_write_label_offset.rb +1 -1
  26. data/test/chart/test_write_lang.rb +1 -1
  27. data/test/chart/test_write_layout.rb +1 -1
  28. data/test/chart/test_write_legend.rb +1 -1
  29. data/test/chart/test_write_legend_pos.rb +1 -1
  30. data/test/chart/test_write_major_gridlines.rb +2 -2
  31. data/test/chart/test_write_marker.rb +1 -1
  32. data/test/chart/test_write_marker_size.rb +1 -1
  33. data/test/chart/test_write_marker_value.rb +1 -1
  34. data/test/chart/test_write_num_cache.rb +1 -1
  35. data/test/chart/test_write_number_format.rb +40 -2
  36. data/test/chart/test_write_order.rb +1 -1
  37. data/test/chart/test_write_orientation.rb +1 -1
  38. data/test/chart/test_write_page_margins.rb +1 -1
  39. data/test/chart/test_write_page_setup.rb +1 -1
  40. data/test/chart/test_write_plot_vis_only.rb +1 -1
  41. data/test/chart/test_write_pt_count.rb +1 -1
  42. data/test/chart/test_write_style.rb +1 -1
  43. data/test/chart/test_write_symbol.rb +1 -1
  44. data/test/chart/test_write_tick_lbl_pos.rb +1 -1
  45. data/test/drawing/test_write_a_graphic_frame_locks.rb +1 -1
  46. data/test/drawing/test_write_c_chart.rb +1 -1
  47. data/test/drawing/test_write_c_nv_graphic_frame_pr.rb +2 -2
  48. data/test/drawing/test_write_c_nv_pr.rb +1 -1
  49. data/test/drawing/test_write_ext.rb +1 -1
  50. data/test/drawing/test_write_pos.rb +1 -1
  51. data/test/drawing/test_write_xfrm_extension.rb +1 -1
  52. data/test/drawing/test_write_xfrm_offset.rb +1 -1
  53. data/test/helper.rb +1 -1
  54. data/test/package/content_types/test_write_default.rb +1 -1
  55. data/test/package/content_types/test_write_override.rb +1 -1
  56. data/test/package/table/test_write_auto_filter.rb +1 -1
  57. data/test/package/table/test_write_table_column.rb +1 -1
  58. data/test/package/table/test_write_table_style_info.rb +1 -1
  59. data/test/package/vml/test_write_fill.rb +1 -1
  60. data/test/package/vml/test_write_idmap.rb +1 -1
  61. data/test/package/vml/test_write_move_with_cells.rb +1 -1
  62. data/test/package/vml/test_write_path.rb +2 -2
  63. data/test/package/vml/test_write_shadow.rb +1 -1
  64. data/test/package/vml/test_write_shapelayout.rb +1 -1
  65. data/test/package/vml/test_write_shapetype.rb +1 -1
  66. data/test/package/vml/test_write_size_with_cells.rb +1 -1
  67. data/test/package/vml/test_write_stroke.rb +1 -1
  68. data/test/perl_output/chart_radar.xlsx +0 -0
  69. data/test/perl_output/chart_secondary_axis.xlsx +0 -0
  70. data/test/regression/test_chart_axis22.rb +45 -0
  71. data/test/regression/test_chart_axis23.rb +46 -0
  72. data/test/regression/test_chart_axis24.rb +46 -0
  73. data/test/regression/test_chart_font01.rb +54 -0
  74. data/test/regression/test_chart_font02.rb +56 -0
  75. data/test/regression/test_chart_font03.rb +59 -0
  76. data/test/regression/test_chart_font04.rb +57 -0
  77. data/test/regression/test_chart_font05.rb +54 -0
  78. data/test/regression/test_chart_font06.rb +84 -0
  79. data/test/regression/test_chart_radar01.rb +39 -0
  80. data/test/regression/test_chart_radar02.rb +43 -0
  81. data/test/regression/test_chart_radar03.rb +43 -0
  82. data/test/regression/test_escapes04.rb +30 -0
  83. data/test/regression/test_escapes05.rb +31 -0
  84. data/test/regression/test_rich_string01.rb +1 -1
  85. data/test/regression/test_rich_string02.rb +1 -1
  86. data/test/regression/test_rich_string03.rb +1 -1
  87. data/test/regression/test_rich_string04.rb +1 -1
  88. data/test/regression/test_rich_string05.rb +1 -1
  89. data/test/regression/test_rich_string06.rb +1 -1
  90. data/test/regression/test_rich_string07.rb +1 -1
  91. data/test/regression/test_rich_string08.rb +1 -1
  92. data/test/regression/test_rich_string09.rb +1 -1
  93. data/test/regression/test_rich_string10.rb +1 -1
  94. data/test/regression/test_rich_string11.rb +1 -1
  95. data/test/regression/test_shape_connect01.rb +1 -1
  96. data/test/regression/test_shape_connect02.rb +1 -1
  97. data/test/regression/test_shape_connect03.rb +1 -1
  98. data/test/regression/test_shape_connect04.rb +1 -1
  99. data/test/regression/xlsx_files/chart_axis22.xlsx +0 -0
  100. data/test/regression/xlsx_files/chart_axis23.xlsx +0 -0
  101. data/test/regression/xlsx_files/chart_axis24.xlsx +0 -0
  102. data/test/regression/xlsx_files/chart_font01.xlsx +0 -0
  103. data/test/regression/xlsx_files/chart_font02.xlsx +0 -0
  104. data/test/regression/xlsx_files/chart_font03.xlsx +0 -0
  105. data/test/regression/xlsx_files/chart_font04.xlsx +0 -0
  106. data/test/regression/xlsx_files/chart_font05.xlsx +0 -0
  107. data/test/regression/xlsx_files/chart_font06.xlsx +0 -0
  108. data/test/regression/xlsx_files/chart_radar01.xlsx +0 -0
  109. data/test/regression/xlsx_files/chart_radar02.xlsx +0 -0
  110. data/test/regression/xlsx_files/chart_radar03.xlsx +0 -0
  111. data/test/regression/xlsx_files/escapes04.xlsx +0 -0
  112. data/test/regression/xlsx_files/escapes05.xlsx +0 -0
  113. data/test/test_example_match.rb +119 -1
  114. data/test/test_xml_writer_simple.rb +4 -4
  115. data/test/worksheet/test_write_autofilter.rb +21 -21
  116. data/test/worksheet/test_write_brk.rb +1 -1
  117. data/test/worksheet/test_write_col_breaks.rb +2 -2
  118. data/test/worksheet/test_write_col_info.rb +6 -6
  119. data/test/worksheet/test_write_custom_filter.rb +1 -1
  120. data/test/worksheet/test_write_custom_filters.rb +2 -2
  121. data/test/worksheet/test_write_dimension.rb +9 -9
  122. data/test/worksheet/test_write_ext.rb +1 -1
  123. data/test/worksheet/test_write_ext_lst.rb +1 -1
  124. data/test/worksheet/test_write_filter.rb +1 -1
  125. data/test/worksheet/test_write_filter_column.rb +1 -1
  126. data/test/worksheet/test_write_filters.rb +3 -3
  127. data/test/worksheet/test_write_hyperlink.rb +4 -4
  128. data/test/worksheet/test_write_hyperlinks.rb +2 -2
  129. data/test/worksheet/test_write_legacy_drawing.rb +1 -1
  130. data/test/worksheet/test_write_merge_cell.rb +1 -1
  131. data/test/worksheet/test_write_mx_plv.rb +1 -1
  132. data/test/worksheet/test_write_page_margins.rb +11 -11
  133. data/test/worksheet/test_write_page_set_up_pr.rb +1 -1
  134. data/test/worksheet/test_write_page_setup.rb +4 -4
  135. data/test/worksheet/test_write_pane.rb +14 -14
  136. data/test/worksheet/test_write_phonetic_pr.rb +1 -1
  137. data/test/worksheet/test_write_print_options.rb +5 -5
  138. data/test/worksheet/test_write_row_breaks.rb +2 -2
  139. data/test/worksheet/test_write_row_element.rb +1 -1
  140. data/test/worksheet/test_write_selection.rb +1 -1
  141. data/test/worksheet/test_write_sheet_calc_pr.rb +1 -1
  142. data/test/worksheet/test_write_sheet_data.rb +1 -1
  143. data/test/worksheet/test_write_sheet_format_pr.rb +1 -1
  144. data/test/worksheet/test_write_sheet_pr.rb +3 -3
  145. data/test/worksheet/test_write_sheet_protection.rb +18 -18
  146. data/test/worksheet/test_write_sheet_view.rb +6 -6
  147. data/test/worksheet/test_write_sheet_view1.rb +6 -6
  148. data/test/worksheet/test_write_sheet_view2.rb +5 -5
  149. data/test/worksheet/test_write_sheet_view3.rb +8 -8
  150. data/test/worksheet/test_write_sheet_view4.rb +8 -8
  151. data/test/worksheet/test_write_sheet_view5.rb +7 -7
  152. data/test/worksheet/test_write_sheet_view6.rb +4 -4
  153. data/test/worksheet/test_write_sheet_view7.rb +6 -6
  154. data/test/worksheet/test_write_sheet_view8.rb +4 -4
  155. data/test/worksheet/test_write_sheet_view9.rb +4 -4
  156. data/test/worksheet/test_write_tab_color.rb +1 -1
  157. data/write_xlsx.gemspec +18 -935
  158. metadata +881 -32
  159. data/VERSION +0 -1
  160. data/test/chart/test_write_num_fmt.rb +0 -16
@@ -58,13 +58,16 @@ module Writexlsx
58
58
  # Creates a Line style chart. See Writexlsx::Chart::Line.
59
59
  #
60
60
  # ===pie
61
- # Creates an Pie style chart. See Writexlsx::Chart::Pie.
61
+ # Creates a Pie style chart. See Writexlsx::Chart::Pie.
62
62
  #
63
63
  # ===scatter
64
- # Creates an Scatter style chart. See Writexlsx::Chart::Scatter.
64
+ # Creates a Scatter style chart. See Writexlsx::Chart::Scatter.
65
65
  #
66
66
  # ===stock
67
- # Creates an Stock style chart. See Writexlsx::Chart::Stock.
67
+ # Creates a Stock style chart. See Writexlsx::Chart::Stock.
68
+ #
69
+ # ===radar
70
+ # Creates a Radar style chart. See Writexlsx::Chart::Radar.
68
71
  #
69
72
  # ==CHART FORMATTING
70
73
  #
@@ -456,6 +459,9 @@ module Writexlsx
456
459
  when 'Pie'
457
460
  require 'write_xlsx/chart/pie'
458
461
  Chart::Pie.new(subtype)
462
+ when 'Radar'
463
+ require 'write_xlsx/chart/radar'
464
+ Chart::Radar.new(subtype)
459
465
  when 'Scatter'
460
466
  require 'write_xlsx/chart/scatter'
461
467
  Chart::Scatter.new(subtype)
@@ -478,7 +484,7 @@ module Writexlsx
478
484
  @style_id = 2
479
485
  @axis_ids = []
480
486
  @axis2_ids = []
481
- @has_category = false
487
+ @cat_has_num_fmt = false
482
488
  @requires_category = 0
483
489
  @legend_position = 'right'
484
490
  @cat_axis_position = 'b'
@@ -790,7 +796,7 @@ module Writexlsx
790
796
  # )
791
797
  #
792
798
  def set_x_axis(params = {})
793
- @x_axis = convert_axis_args(params)
799
+ @x_axis = convert_axis_args(@x_axis, params)
794
800
  end
795
801
 
796
802
  #
@@ -800,42 +806,23 @@ module Writexlsx
800
806
  # The properties that can be set are the same as for set_x_axis,
801
807
  #
802
808
  def set_y_axis(params = {})
803
- @y_axis =
804
- convert_axis_args(
805
- {:major_gridlines => {:visible => 1}}.
806
- merge(params)
807
- )
809
+ @y_axis = convert_axis_args(@y_axis, params)
808
810
  end
809
811
 
810
812
  #
811
813
  # Set the properties of the secondary X-axis.
812
814
  #
813
815
  def set_x2_axis(params = {})
814
- @x2_axis =
815
- convert_axis_args(
816
- {
817
- :label_position => 'none',
818
- :crossing => 'max',
819
- :visible => 0
820
- }.
821
- merge(params)
822
- )
816
+ @x2_axis = convert_axis_args(@x2_axis, params)
823
817
  end
824
818
 
825
819
  #
826
820
  # Set the properties of the secondary Y-axis.
827
821
  #
828
822
  def set_y2_axis(params = {})
829
- @y2_axis =
830
- convert_axis_args(
831
- {
832
- :major_gridlines => {:visible => 0},
833
- :position => 'r',
834
- :visible => 1
835
- }.
836
- merge(params)
837
- )
823
+ @y2_axis = convert_axis_args(@y2_axis, params)
838
824
  end
825
+
839
826
  #
840
827
  # Set the properties of the chart title.
841
828
  #
@@ -857,6 +844,9 @@ module Writexlsx
857
844
  @title_name = name
858
845
  @title_formula = name_formula
859
846
  @title_data_id = data_id
847
+
848
+ # Set the font properties if present.
849
+ @title_font = convert_font_args(params[:name_font])
860
850
  end
861
851
 
862
852
  #
@@ -1125,36 +1115,71 @@ module Writexlsx
1125
1115
  #
1126
1116
  # Convert user defined axis values into private hash values.
1127
1117
  #
1128
- def convert_axis_args(params) # :nodoc:
1129
- name, name_formula = process_names(params[:name], params[:name_formula])
1118
+ def convert_axis_args(axis, params) # :nodoc:
1119
+ arg = (axis[:_defaults] || {}).merge(params)
1120
+ name, name_formula = process_names(arg[:name], arg[:name_formula])
1130
1121
 
1131
- data_id = get_data_id(name_formula, params[:data])
1122
+ data_id = get_data_id(name_formula, arg[:data])
1132
1123
 
1133
1124
  axis = {
1134
- :_name => name,
1135
- :_formula => name_formula,
1136
- :_data_id => data_id,
1137
- :_reverse => params[:reverse],
1138
- :_min => params[:min],
1139
- :_max => params[:max],
1140
- :_minor_unit => params[:minor_unit],
1141
- :_major_unit => params[:major_unit],
1142
- :_minor_unit_type => params[:minor_unit_type],
1143
- :_major_unit_type => params[:major_unit_type],
1144
- :_log_base => params[:log_base],
1145
- :_crossing => params[:crossing],
1146
- :_position => params[:position],
1147
- :_label_position => params[:label_position],
1148
- :_major_gridlines => params[:major_gridlines] || {:visible => 1},
1149
- :_visible => params[:visible] ? params[:visible] : 1
1125
+ :_defaults => axis[:_defaults],
1126
+ :_name => name,
1127
+ :_formula => name_formula,
1128
+ :_data_id => data_id,
1129
+ :_reverse => arg[:reverse],
1130
+ :_min => arg[:min],
1131
+ :_max => arg[:max],
1132
+ :_minor_unit => arg[:minor_unit],
1133
+ :_major_unit => arg[:major_unit],
1134
+ :_minor_unit_type => arg[:minor_unit_type],
1135
+ :_major_unit_type => arg[:major_unit_type],
1136
+ :_log_base => arg[:log_base],
1137
+ :_crossing => arg[:crossing],
1138
+ :_position => arg[:position],
1139
+ :_label_position => arg[:label_position],
1140
+ :_num_format => arg[:num_format],
1141
+ :_num_format_linked => arg[:num_format_linked],
1142
+ :_visible => arg[:visible] || 1
1150
1143
  }
1151
1144
 
1145
+ # Map major_gridlines properties.
1146
+ if arg[:major_gridlines] && ptrue?(arg[:major_gridlines][:visible])
1147
+ axis[:_major_gridlines] = { :_visible => arg[:major_gridlines][:visible] }
1148
+ end
1149
+
1152
1150
  # Only use the first letter of bottom, top, left or right.
1153
1151
  axis[:_position] = axis[:_position].downcase[0, 1] if axis[:_position]
1154
1152
 
1153
+ # Set the font properties if present.
1154
+ axis[:_num_font] = convert_font_args(arg[:num_font])
1155
+ axis[:_name_font] = convert_font_args(arg[:name_font])
1156
+
1155
1157
  axis
1156
1158
  end
1157
1159
 
1160
+ #
1161
+ # Convert user defined font values into private hash values.
1162
+ #
1163
+ def convert_font_args(params)
1164
+ return unless params
1165
+ font = {
1166
+ :_name => params[:name],
1167
+ :_color => params[:color],
1168
+ :_size => params[:size],
1169
+ :_bold => params[:bold],
1170
+ :_italic => params[:italic],
1171
+ :_underline => params[:underline],
1172
+ :_pitch_family => params[:pitch_family],
1173
+ :_charset => params[:charset],
1174
+ :_baseline => params[:baseline] || 0
1175
+ }
1176
+
1177
+ # Convert font size units.
1178
+ font[:_size] *= 100 if font[:_size] && font[:_size] != 0
1179
+
1180
+ font
1181
+ end
1182
+
1158
1183
  #
1159
1184
  # Convert and aref of row col values to a range formula.
1160
1185
  #
@@ -1528,12 +1553,67 @@ module Writexlsx
1528
1553
  end
1529
1554
  end
1530
1555
 
1556
+ #
1557
+ # Get the font style attributes from a font hash.
1558
+ #
1559
+ def get_font_style_attributes(font)
1560
+ return [] unless font
1561
+
1562
+ attributes = []
1563
+ attributes << 'sz' << font[:_size] if ptrue?(font[:_size])
1564
+ attributes << 'b' << font[:_bold] if font[:_bold]
1565
+ attributes << 'i' << font[:_italic] if font[:_italic]
1566
+ attributes << 'u' << 'sng' if font[:_underline]
1567
+
1568
+ attributes << 'baseline' << font[:_baseline]
1569
+ attributes
1570
+ end
1571
+
1572
+ #
1573
+ # Get the font latin attributes from a font hash.
1574
+ #
1575
+ def get_font_latin_attributes(font)
1576
+ return [] unless font
1577
+
1578
+ attributes = []
1579
+ attributes << 'typeface' << font[:_name] if ptrue?(font[:_name])
1580
+ attributes << 'pitchFamily' << font[:_pitch_family] if font[:_pitch_family]
1581
+ attributes << 'charset' << font[:_charset] if font[:_charset]
1582
+
1583
+ attributes
1584
+ end
1531
1585
  #
1532
1586
  # Setup the default properties for a chart.
1533
1587
  #
1534
1588
  def set_default_properties # :nodoc:
1535
1589
  @chartarea = default_chartarea_property
1536
1590
  @plotarea = default_plotarea_property
1591
+
1592
+ # Set the default axis properties.
1593
+ @x_axis[:_defaults] = {
1594
+ :num_format => 'General',
1595
+ :major_gridlines => { :visible => 0 }
1596
+ }
1597
+
1598
+ @y_axis[:_defaults] = {
1599
+ :num_format => 'General',
1600
+ :major_gridlines => { :visible => 1 }
1601
+ }
1602
+
1603
+ @x2_axis[:_defaults] = {
1604
+ :num_format => 'General',
1605
+ :label_position => 'none',
1606
+ :crossing => 'max',
1607
+ :visible => 0
1608
+ }
1609
+
1610
+ @y2_axis[:_defaults] = {
1611
+ :num_format => 'General',
1612
+ :major_gridlines => { :visible => 0 },
1613
+ :position => 'right',
1614
+ :visible => 1
1615
+ }
1616
+
1537
1617
  set_x_axis
1538
1618
  set_y_axis
1539
1619
 
@@ -1638,9 +1718,9 @@ module Writexlsx
1638
1718
  @writer.tag_elements('c:chart') do
1639
1719
  # Write the chart title elements.
1640
1720
  if title = @title_formula
1641
- write_title_formula(title, @title_data_id)
1721
+ write_title_formula(title, @title_data_id, nil, @title_font)
1642
1722
  elsif title = @title_name
1643
- write_title_rich(title)
1723
+ write_title_rich(title, nil, @title_font)
1644
1724
  end
1645
1725
 
1646
1726
  # Write the c:plotArea element.
@@ -1838,16 +1918,15 @@ module Writexlsx
1838
1918
  # Ignore <c:cat> elements for charts without category values.
1839
1919
  return unless formula
1840
1920
 
1841
- @has_category = true
1842
-
1843
1921
  @writer.tag_elements('c:cat') do
1844
1922
  # Check the type of cached data.
1845
1923
  type = get_data_type(data)
1846
1924
  if type == 'str'
1847
- @has_category = false
1925
+ @cat_has_num_fmt = false
1848
1926
  # Write the c:strRef element.
1849
1927
  write_str_ref(formula, data, type)
1850
1928
  else
1929
+ @cat_has_num_fmt = true
1851
1930
  # Write the c:numRef element.
1852
1931
  write_num_ref(formula, data, type)
1853
1932
  end
@@ -1967,16 +2046,29 @@ module Writexlsx
1967
2046
 
1968
2047
  # Write the c:axPos element.
1969
2048
  write_axis_pos(position, y_axis[:_reverse])
2049
+
2050
+ # Write the c:majorGridlines element.
2051
+ write_major_gridlines(x_axis[:_major_gridlines])
2052
+
1970
2053
  # Write the axis title elements.
1971
2054
  if title = x_axis[:_formula]
1972
- write_title_formula(title, @x_axis[:_data_id], horiz)
2055
+ write_title_formula(title, @x_axis[:_data_id], horiz, @x_axis[:_name_font])
1973
2056
  elsif title = x_axis[:_name]
1974
- write_title_rich(title, horiz)
2057
+ write_title_rich(title, horiz, x_axis[:_name_font])
1975
2058
  end
2059
+
1976
2060
  # Write the c:numFmt element.
1977
- write_num_fmt
2061
+ write_cat_number_format(x_axis)
2062
+
2063
+ # Write the c:majorTickMark element.
2064
+ write_major_tick_mark(x_axis[:_major_tick_mark])
2065
+
1978
2066
  # Write the c:tickLblPos element.
1979
2067
  write_tick_label_pos(x_axis[:_label_position])
2068
+
2069
+ # Write the axis font elements.
2070
+ write_axis_font(x_axis[:_num_font])
2071
+
1980
2072
  # Write the c:crossAx element.
1981
2073
  write_cross_axis(axis_ids[1])
1982
2074
 
@@ -2025,17 +2117,23 @@ module Writexlsx
2025
2117
 
2026
2118
  # Write the axis title elements.
2027
2119
  if title = y_axis[:_formula]
2028
- write_title_formula(title, y_axis[:_data_id], horiz)
2120
+ write_title_formula(title, y_axis[:_data_id], horiz, y_axis[:_name_font])
2029
2121
  elsif title = y_axis[:_name]
2030
- write_title_rich(title, horiz)
2122
+ write_title_rich(title, horiz, y_axis[:_name_font])
2031
2123
  end
2032
2124
 
2033
2125
  # Write the c:numberFormat element.
2034
- write_number_format
2126
+ write_number_format(y_axis)
2127
+
2128
+ # Write the c:majorTickMark element.
2129
+ write_major_tick_mark(y_axis[:_major_tick_mark])
2035
2130
 
2036
2131
  # Write the tickLblPos element.
2037
2132
  write_tick_label_pos(y_axis[:_label_position])
2038
2133
 
2134
+ # Write the axis font elements.
2135
+ write_axis_font(y_axis[:_num_font])
2136
+
2039
2137
  # Write the c:crossAx element.
2040
2138
  write_cross_axis(axis_ids[0])
2041
2139
 
@@ -2082,17 +2180,23 @@ module Writexlsx
2082
2180
 
2083
2181
  # Write the axis title elements.
2084
2182
  if title = x_axis[:_formula]
2085
- write_title_formula(title, y_axis[:_data_id], horiz)
2183
+ write_title_formula(title, y_axis[:_data_id], horiz, x_axis[:_name_font])
2086
2184
  elsif title = x_axis[:_name]
2087
- write_title_rich(title, horiz)
2185
+ write_title_rich(title, horiz, x_axis[:_name_font])
2088
2186
  end
2089
2187
 
2090
2188
  # Write the c:numberFormat element.
2091
- write_number_format
2189
+ write_number_format(x_axis)
2190
+
2191
+ # Write the c:majorTickMark element.
2192
+ write_major_tick_mark(x_axis[:_major_tick_mark])
2092
2193
 
2093
2194
  # Write the c:tickLblPos element.
2094
2195
  write_tick_label_pos(x_axis[:_label_position])
2095
2196
 
2197
+ # Write the axis font elements.
2198
+ write_axis_font(x_axis[:_num_font])
2199
+
2096
2200
  # Write the c:crossAx element.
2097
2201
  write_cross_axis(axis_ids[1])
2098
2202
 
@@ -2175,14 +2279,19 @@ module Writexlsx
2175
2279
  write_axis_pos(position, y_axis[:reverse])
2176
2280
  # Write the axis title elements.
2177
2281
  if title = x_axis[:_formula]
2178
- write_title_formula(title, x_axis[:_data_id])
2282
+ write_title_formula(title, x_axis[:_data_id], nil, x_axis[:_name_font])
2179
2283
  elsif title = x_axis[:_name]
2180
- write_title_rich(title)
2284
+ write_title_rich(title, nil, x_axis[:_name_font])
2181
2285
  end
2182
2286
  # Write the c:numFmt element.
2183
- write_num_fmt('dd/mm/yyyy')
2287
+ write_number_format(x_axis)
2288
+ # Write the c:majorTickMark element.
2289
+ write_major_tick_mark(x_axis[:_major_tick_mark])
2290
+
2184
2291
  # Write the c:tickLblPos element.
2185
2292
  write_tick_label_pos(x_axis[:_label_position])
2293
+ # Write the font elements.
2294
+ write_axis_font(x_axis[:_num_font])
2186
2295
  # Write the c:crossAx element.
2187
2296
  write_cross_axis(axis_ids[1])
2188
2297
 
@@ -2303,14 +2412,24 @@ module Writexlsx
2303
2412
  end
2304
2413
 
2305
2414
  #
2306
- # Write the <c:numFmt> element.
2415
+ # Write the <c:numberFormat> element. Note: It is assumed that if a user
2416
+ # defined number format is supplied (i.e., non-default) then the sourceLinked
2417
+ # attribute is 0. The user can override this if required.
2307
2418
  #
2308
- def write_num_fmt(format_code = nil) # :nodoc:
2309
- format_code ||= 'General'
2419
+
2420
+ def write_number_format(axis) # :nodoc:
2421
+ format_code = axis[:_num_format]
2310
2422
  source_linked = 1
2311
2423
 
2312
- # These elements are only required for charts with categories.
2313
- return unless @has_category
2424
+ # Check if a user defined number format has been set.
2425
+ if axis[:_defaults] && format_code != axis[:_defaults][:num_format]
2426
+ source_linked = 0
2427
+ end
2428
+
2429
+ # User override of sourceLinked.
2430
+ if ptrue?(axis[:_num_format_linked])
2431
+ source_linked = 1
2432
+ end
2314
2433
 
2315
2434
  attributes = [
2316
2435
  'formatCode', format_code,
@@ -2320,6 +2439,50 @@ module Writexlsx
2320
2439
  @writer.empty_tag('c:numFmt', attributes)
2321
2440
  end
2322
2441
 
2442
+ #
2443
+ # Write the <c:numFmt> element. Special case handler for category axes which
2444
+ # don't always have a number format.
2445
+ #
2446
+ def write_cat_number_format(axis)
2447
+ format_code = axis[:_num_format]
2448
+ source_linked = 1
2449
+ default_format = true
2450
+
2451
+ # Check if a user defined number format has been set.
2452
+ if axis[:_defaults] && format_code != axis[:_defaults][:num_format]
2453
+ source_linked = 0
2454
+ default_format = false
2455
+ end
2456
+
2457
+ # User override of linkedSource.
2458
+ if axis[:_num_format_linked]
2459
+ source_linked = 1
2460
+ end
2461
+
2462
+ # Skip if cat doesn't have a num format (unless it is non-default).
2463
+ if !@cat_has_num_fmt && default_format
2464
+ return ''
2465
+ end
2466
+
2467
+ attributes = [
2468
+ 'formatCode', format_code,
2469
+ 'sourceLinked', source_linked,
2470
+ ]
2471
+
2472
+ @writer.empty_tag('c:numFmt', attributes)
2473
+ end
2474
+
2475
+ #
2476
+ # Write the <c:majorTickMark> element.
2477
+ #
2478
+ def write_major_tick_mark(val)
2479
+ return unless ptrue?(val)
2480
+
2481
+ attributes = ['val', val]
2482
+
2483
+ @writer.empty_tag('c:majorTickMark', attributes)
2484
+ end
2485
+
2323
2486
  #
2324
2487
  # Write the <c:tickLblPos> element.
2325
2488
  #
@@ -2391,29 +2554,13 @@ module Writexlsx
2391
2554
  #
2392
2555
  # Write the <c:majorGridlines> element.
2393
2556
  #
2394
- def write_major_gridlines(options = {}) # :nodoc:
2395
- return unless ptrue?(options[:visible])
2557
+ def write_major_gridlines(gridlines) # :nodoc:
2558
+ return unless gridlines
2559
+ return unless ptrue?(gridlines[:_visible])
2396
2560
 
2397
2561
  @writer.empty_tag('c:majorGridlines')
2398
2562
  end
2399
2563
 
2400
- #
2401
- # Write the <c:numberFormat> element.
2402
- #
2403
- # TODO. Merge/replace with _write_num_fmt.
2404
- #
2405
- def write_number_format # :nodoc:
2406
- format_code = 'General'
2407
- source_linked = 1
2408
-
2409
- attributes = [
2410
- 'formatCode', format_code,
2411
- 'sourceLinked', source_linked
2412
- ]
2413
-
2414
- @writer.empty_tag('c:numFmt', attributes)
2415
- end
2416
-
2417
2564
  #
2418
2565
  # Write the <c:crossBetween> element.
2419
2566
  #
@@ -2548,7 +2695,7 @@ module Writexlsx
2548
2695
  def write_plot_vis_only # :nodoc:
2549
2696
  val = 1
2550
2697
 
2551
- # Ignore this element if we are plitting hidden data.
2698
+ # Ignore this element if we are plotting hidden data.
2552
2699
  return if @show_hidden_data
2553
2700
 
2554
2701
  attributes = ['val', val]
@@ -2610,10 +2757,10 @@ module Writexlsx
2610
2757
  #
2611
2758
  # Write the <c:title> element for a rich string.
2612
2759
  #
2613
- def write_title_rich(title, horiz = nil) # :nodoc:
2760
+ def write_title_rich(title, horiz = nil, font = nil) # :nodoc:
2614
2761
  @writer.tag_elements('c:title') do
2615
2762
  # Write the c:tx element.
2616
- write_tx_rich(title, horiz)
2763
+ write_tx_rich(title, horiz, font)
2617
2764
  # Write the c:layout element.
2618
2765
  write_layout
2619
2766
  end
@@ -2622,22 +2769,22 @@ module Writexlsx
2622
2769
  #
2623
2770
  # Write the <c:title> element for a rich string.
2624
2771
  #
2625
- def write_title_formula(title, data_id, horiz = nil) # :nodoc:
2772
+ def write_title_formula(title, data_id, horiz = nil, font = nil) # :nodoc:
2626
2773
  @writer.tag_elements('c:title') do
2627
2774
  # Write the c:tx element.
2628
2775
  write_tx_formula(title, data_id)
2629
2776
  # Write the c:layout element.
2630
2777
  write_layout
2631
2778
  # Write the c:txPr element.
2632
- write_tx_pr(horiz)
2779
+ write_tx_pr(horiz, font)
2633
2780
  end
2634
2781
  end
2635
2782
 
2636
2783
  #
2637
2784
  # Write the <c:tx> element.
2638
2785
  #
2639
- def write_tx_rich(title, horiz) # :nodoc:
2640
- @writer.tag_elements('c:tx') { write_rich(title, horiz) }
2786
+ def write_tx_rich(title, horiz, font = nil) # :nodoc:
2787
+ @writer.tag_elements('c:tx') { write_rich(title, horiz, font) }
2641
2788
  end
2642
2789
 
2643
2790
  #
@@ -2659,14 +2806,14 @@ module Writexlsx
2659
2806
  #
2660
2807
  # Write the <c:rich> element.
2661
2808
  #
2662
- def write_rich(title, horiz) # :nodoc:
2809
+ def write_rich(title, horiz, font) # :nodoc:
2663
2810
  @writer.tag_elements('c:rich') do
2664
2811
  # Write the a:bodyPr element.
2665
2812
  write_a_body_pr(horiz)
2666
2813
  # Write the a:lstStyle element.
2667
2814
  write_a_lst_style
2668
2815
  # Write the a:p element.
2669
- write_a_p_rich(title)
2816
+ write_a_p_rich(title, font)
2670
2817
  end
2671
2818
  end
2672
2819
 
@@ -2697,22 +2844,22 @@ module Writexlsx
2697
2844
  #
2698
2845
  # Write the <a:p> element for rich string titles.
2699
2846
  #
2700
- def write_a_p_rich(title) # :nodoc:
2847
+ def write_a_p_rich(title, font) # :nodoc:
2701
2848
  @writer.tag_elements('a:p') do
2702
2849
  # Write the a:pPr element.
2703
- write_a_p_pr_rich
2850
+ write_a_p_pr_rich(font)
2704
2851
  # Write the a:r element.
2705
- write_a_r(title)
2852
+ write_a_r(title, font)
2706
2853
  end
2707
2854
  end
2708
2855
 
2709
2856
  #
2710
2857
  # Write the <a:p> element for formula titles.
2711
2858
  #
2712
- def write_a_p_formula # :nodoc:
2859
+ def write_a_p_formula(font = nil) # :nodoc:
2713
2860
  @writer.tag_elements('a:p') do
2714
2861
  # Write the a:pPr element.
2715
- write_a_p_pr_formula
2862
+ write_a_p_pr_formula(font)
2716
2863
  # Write the a:endParaRPr element.
2717
2864
  write_a_end_para_rpr
2718
2865
  end
@@ -2721,22 +2868,37 @@ module Writexlsx
2721
2868
  #
2722
2869
  # Write the <a:pPr> element for rich string titles.
2723
2870
  #
2724
- def write_a_p_pr_rich # :nodoc:
2725
- @writer.tag_elements('a:pPr') { write_a_def_rpr }
2871
+ def write_a_p_pr_rich(font) # :nodoc:
2872
+ @writer.tag_elements('a:pPr') { write_a_def_rpr(font) }
2726
2873
  end
2727
2874
 
2728
2875
  #
2729
2876
  # Write the <a:pPr> element for formula titles.
2730
2877
  #
2731
- def write_a_p_pr_formula # :nodoc:
2732
- @writer.tag_elements('a:pPr') { write_a_def_rpr }
2878
+ def write_a_p_pr_formula(font) # :nodoc:
2879
+ @writer.tag_elements('a:pPr') { write_a_def_rpr(font) }
2733
2880
  end
2734
2881
 
2735
2882
  #
2736
2883
  # Write the <a:defRPr> element.
2737
2884
  #
2738
- def write_a_def_rpr # :nodoc:
2739
- @writer.empty_tag('a:defRPr')
2885
+ def write_a_def_rpr(font = nil) # :nodoc:
2886
+ style_attributes = get_font_style_attributes(font)
2887
+ latin_attributes = get_font_latin_attributes(font)
2888
+ has_color = ptrue?(font) && ptrue?(font[:_color])
2889
+
2890
+ if !latin_attributes.empty? || has_color
2891
+ @writer.tag_elements('a:defRPr', style_attributes) do
2892
+ if has_color
2893
+ write_a_solid_fill(:color => font[:_color])
2894
+ end
2895
+ if !latin_attributes.empty?
2896
+ write_a_latin(latin_attributes)
2897
+ end
2898
+ end
2899
+ else
2900
+ @writer.empty_tag('a:defRPr', style_attributes)
2901
+ end
2740
2902
  end
2741
2903
 
2742
2904
  #
@@ -2753,10 +2915,10 @@ module Writexlsx
2753
2915
  #
2754
2916
  # Write the <a:r> element.
2755
2917
  #
2756
- def write_a_r(title) # :nodoc:
2918
+ def write_a_r(title, font) # :nodoc:
2757
2919
  @writer.tag_elements('a:r') do
2758
2920
  # Write the a:rPr element.
2759
- write_a_r_pr
2921
+ write_a_r_pr(font)
2760
2922
  # Write the a:t element.
2761
2923
  write_a_t(title)
2762
2924
  end
@@ -2765,12 +2927,28 @@ module Writexlsx
2765
2927
  #
2766
2928
  # Write the <a:rPr> element.
2767
2929
  #
2768
- def write_a_r_pr # :nodoc:
2930
+ def write_a_r_pr(font) # :nodoc:
2769
2931
  lang = 'en-US'
2770
2932
 
2771
- attributes = ['lang', lang]
2933
+ style_attributes = get_font_style_attributes(font)
2934
+ latin_attributes = get_font_latin_attributes(font)
2935
+ has_color = ptrue?(font) && ptrue?(font[:_color])
2936
+
2937
+ # Add the lang type to the attributes.
2938
+ style_attributes.unshift(lang).unshift('lang')
2772
2939
 
2773
- @writer.empty_tag('a:rPr', attributes)
2940
+ if !latin_attributes.empty? || has_color
2941
+ @writer.tag_elements('a:rPr', style_attributes) do
2942
+ if has_color
2943
+ write_a_solid_fill(:color => font[:_color])
2944
+ end
2945
+ if !latin_attributes.empty?
2946
+ write_a_latin(latin_attributes)
2947
+ end
2948
+ end
2949
+ else
2950
+ @writer.empty_tag('a:rPr', style_attributes)
2951
+ end
2774
2952
  end
2775
2953
 
2776
2954
  #
@@ -2783,14 +2961,14 @@ module Writexlsx
2783
2961
  #
2784
2962
  # Write the <c:txPr> element.
2785
2963
  #
2786
- def write_tx_pr(horiz) # :nodoc:
2964
+ def write_tx_pr(horiz, font) # :nodoc:
2787
2965
  @writer.tag_elements('c:txPr') do
2788
2966
  # Write the a:bodyPr element.
2789
2967
  write_a_body_pr(horiz)
2790
2968
  # Write the a:lstStyle element.
2791
2969
  write_a_lst_style
2792
2970
  # Write the a:p element.
2793
- write_a_p_formula
2971
+ write_a_p_formula(font)
2794
2972
  end
2795
2973
  end
2796
2974
 
@@ -3233,7 +3411,30 @@ module Writexlsx
3233
3411
  @writer.empty_tag('c:invertIfNegative', attributes)
3234
3412
  end
3235
3413
 
3236
- def nil_or_max?(val)
3414
+ #
3415
+ # Write the axis font elements.
3416
+ #
3417
+ def write_axis_font(font) # :nodoc:
3418
+ return unless font
3419
+
3420
+ @writer.tag_elements('c:txPr') do
3421
+ @writer.empty_tag('a:bodyPr')
3422
+ write_a_lst_style
3423
+ @writer.tag_elements('a:p') do
3424
+ write_a_p_pr_rich(font)
3425
+ write_a_end_para_rpr
3426
+ end
3427
+ end
3428
+ end
3429
+
3430
+ #
3431
+ # Write the <a:latin> element.
3432
+ #
3433
+ def write_a_latin(args) # :nodoc:
3434
+ @writer.empty_tag('a:latin', args)
3435
+ end
3436
+
3437
+ def nil_or_max?(val) # :nodoc:
3237
3438
  val.nil? || val == 'max'
3238
3439
  end
3239
3440
  end