axlsx 2.0.1 → 2.1.0.pre

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 (155) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -3
  3. data/Rakefile +9 -10
  4. data/examples/IMAGE1UP.JPEG +0 -0
  5. data/examples/auto_filter.rb +10 -1
  6. data/examples/conditional_formatting/example_conditional_formatting.rb +3 -3
  7. data/examples/example.rb +72 -4
  8. data/examples/merge_cells.rb +17 -0
  9. data/examples/no_grid_with_borders.rb +18 -0
  10. data/examples/pivot_test.rb +63 -0
  11. data/examples/split.rb +16 -0
  12. data/lib/axlsx.rb +30 -16
  13. data/lib/axlsx/content_type/abstract_content_type.rb +1 -1
  14. data/lib/axlsx/content_type/content_type.rb +1 -1
  15. data/lib/axlsx/doc_props/app.rb +1 -1
  16. data/lib/axlsx/doc_props/core.rb +5 -5
  17. data/lib/axlsx/drawing/axes.rb +1 -1
  18. data/lib/axlsx/drawing/axis.rb +12 -9
  19. data/lib/axlsx/drawing/bar_3D_chart.rb +13 -13
  20. data/lib/axlsx/drawing/bar_series.rb +9 -9
  21. data/lib/axlsx/drawing/bubble_chart.rb +59 -0
  22. data/lib/axlsx/drawing/bubble_series.rb +63 -0
  23. data/lib/axlsx/drawing/cat_axis.rb +5 -5
  24. data/lib/axlsx/drawing/chart.rb +44 -7
  25. data/lib/axlsx/drawing/drawing.rb +3 -1
  26. data/lib/axlsx/drawing/graphic_frame.rb +3 -3
  27. data/lib/axlsx/drawing/hyperlink.rb +1 -3
  28. data/lib/axlsx/drawing/line_3D_chart.rb +2 -2
  29. data/lib/axlsx/drawing/line_chart.rb +10 -10
  30. data/lib/axlsx/drawing/line_series.rb +14 -2
  31. data/lib/axlsx/drawing/marker.rb +1 -1
  32. data/lib/axlsx/drawing/num_data.rb +4 -4
  33. data/lib/axlsx/drawing/num_data_source.rb +6 -6
  34. data/lib/axlsx/drawing/num_val.rb +1 -1
  35. data/lib/axlsx/drawing/one_cell_anchor.rb +1 -1
  36. data/lib/axlsx/drawing/pic.rb +2 -3
  37. data/lib/axlsx/drawing/picture_locking.rb +1 -3
  38. data/lib/axlsx/drawing/pie_3D_chart.rb +5 -6
  39. data/lib/axlsx/drawing/pie_series.rb +6 -6
  40. data/lib/axlsx/drawing/scaling.rb +4 -4
  41. data/lib/axlsx/drawing/scatter_chart.rb +10 -10
  42. data/lib/axlsx/drawing/scatter_series.rb +26 -7
  43. data/lib/axlsx/drawing/ser_axis.rb +2 -2
  44. data/lib/axlsx/drawing/series.rb +3 -3
  45. data/lib/axlsx/drawing/series_title.rb +2 -2
  46. data/lib/axlsx/drawing/str_data.rb +3 -3
  47. data/lib/axlsx/drawing/str_val.rb +1 -1
  48. data/lib/axlsx/drawing/title.rb +3 -3
  49. data/lib/axlsx/drawing/val_axis.rb +1 -1
  50. data/lib/axlsx/drawing/vml_drawing.rb +1 -1
  51. data/lib/axlsx/package.rb +39 -28
  52. data/lib/axlsx/rels/relationship.rb +1 -1
  53. data/lib/axlsx/rels/relationships.rb +2 -2
  54. data/lib/axlsx/stylesheet/border_pr.rb +2 -2
  55. data/lib/axlsx/stylesheet/cell_alignment.rb +1 -3
  56. data/lib/axlsx/stylesheet/cell_protection.rb +1 -3
  57. data/lib/axlsx/stylesheet/cell_style.rb +1 -3
  58. data/lib/axlsx/stylesheet/color.rb +1 -3
  59. data/lib/axlsx/stylesheet/font.rb +1 -1
  60. data/lib/axlsx/stylesheet/gradient_stop.rb +1 -1
  61. data/lib/axlsx/stylesheet/num_fmt.rb +1 -3
  62. data/lib/axlsx/stylesheet/pattern_fill.rb +1 -1
  63. data/lib/axlsx/stylesheet/styles.rb +6 -6
  64. data/lib/axlsx/stylesheet/table_style_element.rb +1 -3
  65. data/lib/axlsx/util/accessors.rb +6 -6
  66. data/lib/axlsx/util/constants.rb +106 -101
  67. data/lib/axlsx/util/options_parser.rb +2 -1
  68. data/lib/axlsx/util/parser.rb +4 -4
  69. data/lib/axlsx/util/serialized_attributes.rb +16 -6
  70. data/lib/axlsx/util/simple_typed_list.rb +28 -52
  71. data/lib/axlsx/util/storage.rb +4 -4
  72. data/lib/axlsx/util/string.rb +7 -0
  73. data/lib/axlsx/util/validators.rb +20 -13
  74. data/lib/axlsx/version.rb +1 -1
  75. data/lib/axlsx/workbook/defined_name.rb +11 -12
  76. data/lib/axlsx/workbook/defined_names.rb +2 -2
  77. data/lib/axlsx/workbook/shared_strings_table.rb +5 -5
  78. data/lib/axlsx/workbook/workbook.rb +19 -12
  79. data/lib/axlsx/workbook/workbook_view.rb +78 -0
  80. data/lib/axlsx/workbook/workbook_views.rb +22 -0
  81. data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +2 -2
  82. data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +1 -3
  83. data/lib/axlsx/workbook/worksheet/break.rb +1 -3
  84. data/lib/axlsx/workbook/worksheet/cell.rb +128 -73
  85. data/lib/axlsx/workbook/worksheet/cell_serializer.rb +50 -40
  86. data/lib/axlsx/workbook/worksheet/cfvo.rb +1 -3
  87. data/lib/axlsx/workbook/worksheet/cfvos.rb +1 -1
  88. data/lib/axlsx/workbook/worksheet/col.rb +7 -10
  89. data/lib/axlsx/workbook/worksheet/col_breaks.rb +2 -2
  90. data/lib/axlsx/workbook/worksheet/comment.rb +5 -6
  91. data/lib/axlsx/workbook/worksheet/comments.rb +9 -12
  92. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +1 -1
  93. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
  94. data/lib/axlsx/workbook/worksheet/data_bar.rb +4 -6
  95. data/lib/axlsx/workbook/worksheet/data_validation.rb +6 -4
  96. data/lib/axlsx/workbook/worksheet/dimension.rb +2 -2
  97. data/lib/axlsx/workbook/worksheet/header_footer.rb +6 -8
  98. data/lib/axlsx/workbook/worksheet/icon_set.rb +3 -5
  99. data/lib/axlsx/workbook/worksheet/merged_cells.rb +2 -2
  100. data/lib/axlsx/workbook/worksheet/page_margins.rb +1 -3
  101. data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -1
  102. data/lib/axlsx/workbook/worksheet/page_setup.rb +21 -23
  103. data/lib/axlsx/workbook/worksheet/pane.rb +1 -3
  104. data/lib/axlsx/workbook/worksheet/pivot_table.rb +17 -24
  105. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -4
  106. data/lib/axlsx/workbook/worksheet/print_options.rb +1 -3
  107. data/lib/axlsx/workbook/worksheet/protected_range.rb +1 -3
  108. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +1 -1
  109. data/lib/axlsx/workbook/worksheet/rich_text.rb +35 -0
  110. data/lib/axlsx/workbook/worksheet/rich_text_run.rb +254 -0
  111. data/lib/axlsx/workbook/worksheet/row.rb +33 -51
  112. data/lib/axlsx/workbook/worksheet/row_breaks.rb +2 -2
  113. data/lib/axlsx/workbook/worksheet/selection.rb +1 -3
  114. data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
  115. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -3
  116. data/lib/axlsx/workbook/worksheet/table.rb +6 -6
  117. data/lib/axlsx/workbook/worksheet/table_style_info.rb +1 -3
  118. data/lib/axlsx/workbook/worksheet/tables.rb +1 -1
  119. data/lib/axlsx/workbook/worksheet/worksheet.rb +59 -30
  120. data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +3 -3
  121. data/test/drawing/tc_axis.rb +27 -0
  122. data/test/drawing/tc_bubble_chart.rb +44 -0
  123. data/test/drawing/tc_bubble_series.rb +21 -0
  124. data/test/drawing/tc_data_source.rb +6 -0
  125. data/test/drawing/tc_line_chart.rb +5 -5
  126. data/test/drawing/tc_line_series.rb +10 -2
  127. data/test/drawing/tc_pic.rb +4 -0
  128. data/test/drawing/tc_scatter_series.rb +25 -1
  129. data/test/tc_helper.rb +1 -1
  130. data/test/tc_package.rb +7 -1
  131. data/test/util/tc_simple_typed_list.rb +1 -2
  132. data/test/workbook/tc_defined_name.rb +12 -4
  133. data/test/workbook/tc_workbook.rb +16 -2
  134. data/test/workbook/tc_workbook_view.rb +50 -0
  135. data/test/workbook/worksheet/auto_filter/tc_filters.rb +1 -1
  136. data/test/workbook/worksheet/tc_break.rb +1 -1
  137. data/test/workbook/worksheet/tc_cell.rb +30 -4
  138. data/test/workbook/worksheet/tc_col.rb +2 -2
  139. data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
  140. data/test/workbook/worksheet/tc_data_bar.rb +1 -1
  141. data/test/workbook/worksheet/tc_data_validation.rb +11 -11
  142. data/test/workbook/worksheet/tc_header_footer.rb +2 -2
  143. data/test/workbook/worksheet/tc_icon_set.rb +1 -1
  144. data/test/workbook/worksheet/tc_page_setup.rb +3 -3
  145. data/test/workbook/worksheet/tc_print_options.rb +1 -1
  146. data/test/workbook/worksheet/tc_rich_text.rb +44 -0
  147. data/test/workbook/worksheet/tc_rich_text_run.rb +172 -0
  148. data/test/workbook/worksheet/tc_row.rb +2 -2
  149. data/test/workbook/worksheet/tc_sheet_calc_pr.rb +1 -1
  150. data/test/workbook/worksheet/tc_sheet_format_pr.rb +4 -4
  151. data/test/workbook/worksheet/tc_sheet_protection.rb +5 -5
  152. data/test/workbook/worksheet/tc_sheet_view.rb +4 -4
  153. data/test/workbook/worksheet/tc_worksheet.rb +49 -10
  154. metadata +81 -55
  155. data/test/axlsx.qcachegrind +0 -2226
@@ -63,11 +63,9 @@ module Axlsx
63
63
  # @param [String] str
64
64
  # @return [String]
65
65
  def to_xml_string(str="")
66
- str << '<iconSet '
67
- serialized_attributes str
68
- str << '>'
69
- @value_objects.each { |cfvo| cfvo.to_xml_string(str) }
70
- str << '</iconSet>'
66
+ serialized_tag('iconSet', str) do
67
+ @value_objects.each { |cfvo| cfvo.to_xml_string(str) }
68
+ end
71
69
  end
72
70
 
73
71
  private
@@ -15,7 +15,7 @@ module Axlsx
15
15
  # collection. This can be an array of actual cells or a string style
16
16
  # range like 'A1:C1'
17
17
  def add(cells)
18
- @list << if cells.is_a?(String)
18
+ self << if cells.is_a?(String)
19
19
  cells
20
20
  elsif cells.is_a?(Array)
21
21
  Axlsx::cell_range(cells, false)
@@ -26,7 +26,7 @@ module Axlsx
26
26
  # @param [String] str
27
27
  # @return [String]
28
28
  def to_xml_string(str = '')
29
- return if @list.empty?
29
+ return if empty?
30
30
  str << "<mergeCells count='#{size}'>"
31
31
  each { |merged_cell| str << "<mergeCell ref='#{merged_cell}'></mergeCell>" }
32
32
  str << '</mergeCells>'
@@ -91,9 +91,7 @@ module Axlsx
91
91
  # @note For compatibility, this is a noop unless custom margins have been specified.
92
92
  # @see #custom_margins_specified?
93
93
  def to_xml_string(str = '')
94
- str << '<pageMargins '
95
- serialized_attributes str
96
- str << '/>'
94
+ serialized_tag('pageMargins', str)
97
95
  end
98
96
  end
99
97
  end
@@ -38,7 +38,7 @@ module Axlsx
38
38
 
39
39
  # serialize to xml
40
40
  def to_xml_string(str='')
41
- str << '<pageSetUpPr ' << serialized_attributes << '/>'
41
+ str << ('<pageSetUpPr ' << serialized_attributes << '/>')
42
42
  end
43
43
  end
44
44
  end
@@ -44,13 +44,13 @@ module Axlsx
44
44
 
45
45
  # Number of horizontal pages to fit on.
46
46
  # @note PageSetup#fit_to is the recomended way to manage page fitting as only specifying one of width/height will result in the counterpart
47
- # being set to 1.
47
+ # being set to 1.
48
48
  # @return [Integer]
49
49
  attr_reader :fit_to_width
50
50
 
51
51
  # Orientation of the page (:default, :landscape, :portrait)
52
52
  # @return [Symbol]
53
- attr_reader :orientation
53
+ attr_reader :orientation
54
54
 
55
55
  # Height of paper (string containing a number followed by a unit identifier: "297mm", "11in")
56
56
  # @return [String]
@@ -74,18 +74,18 @@ module Axlsx
74
74
  #7 = Executive paper (7.25 in. by 10.5 in.)
75
75
  #8 = A3 paper (297 mm by 420 mm)
76
76
  #9 = A4 paper (210 mm by 297 mm)
77
- #10 = A4 small paper (210 mm by 297 mm)
77
+ #10 = A4 small paper (210 mm by 297 mm)
78
78
  #11 = A5 paper (148 mm by 210 mm)
79
79
  #12 = B4 paper (250 mm by 353 mm)
80
80
  #13 = B5 paper (176 mm by 250 mm)
81
81
  #14 = Folio paper (8.5 in. by 13 in.)
82
- #15 = Quarto paper (215 mm by 275 mm)
82
+ #15 = Quarto paper (215 mm by 275 mm)
83
83
  #16 = Standard paper (10 in. by 14 in.)
84
84
  #17 = Standard paper (11 in. by 17 in.)
85
85
  #18 = Note paper (8.5 in. by 11 in.)
86
- #19 = #9 envelope (3.875 in. by 8.875 in.)
87
- #20 = #10 envelope (4.125 in. by 9.5 in.)
88
- #21 = #11 envelope (4.5 in. by 10.375 in.)
86
+ #19 = #9 envelope (3.875 in. by 8.875 in.)
87
+ #20 = #10 envelope (4.125 in. by 9.5 in.)
88
+ #21 = #11 envelope (4.5 in. by 10.375 in.)
89
89
  #22 = #12 envelope (4.75 in. by 11 in.)
90
90
  #23 = #14 envelope (5 in. by 11.5 in.) 24 = C paper (17 in. by 22 in.)
91
91
  #25 = D paper (22 in. by 34 in.)
@@ -105,7 +105,7 @@ module Axlsx
105
105
  #40 = German standard fanfold (8.5 in. by 12 in.)
106
106
  #41 = German legal fanfold (8.5 in. by 13 in.)
107
107
  #42 = ISO B4 (250 mm by 353 mm)
108
- #43 = Japanese double postcard (200 mm by 148 mm)
108
+ #43 = Japanese double postcard (200 mm by 148 mm)
109
109
  #44 = Standard paper (9 in. by 11 in.)
110
110
  #45 = Standard paper (10 in. by 11 in.)
111
111
  #46 = Standard paper (15 in. by 11 in.)
@@ -116,9 +116,9 @@ module Axlsx
116
116
  #53 = A4 extra paper (236 mm by 322 mm)
117
117
  #54 = Letter transverse paper (8.275 in. by 11 in.)
118
118
  #55 = A4 transverse paper (210 mm by 297 mm)
119
- #56 = Letter extra transverse paper (9.275 in. by 12 in.)
120
- #57 = SuperA/SuperA/A4 paper (227 mm by 356 mm)
121
- #58 = SuperB/SuperB/A3 paper (305 mm by 487 mm)
119
+ #56 = Letter extra transverse paper (9.275 in. by 12 in.)
120
+ #57 = SuperA/SuperA/A4 paper (227 mm by 356 mm)
121
+ #58 = SuperB/SuperB/A3 paper (305 mm by 487 mm)
122
122
  #59 = Letter plus paper (8.5 in. by 12.69 in.)
123
123
  #60 = A4 plus paper (210 mm by 330 mm)
124
124
  #61 = A5 transverse paper (148 mm by 210 mm)
@@ -128,8 +128,8 @@ module Axlsx
128
128
  #65 = ISO B5 extra paper (201 mm by 276 mm)
129
129
  #66 = A2 paper (420 mm by 594 mm)
130
130
  #67 = A3 transverse paper (297 mm by 420 mm)
131
- #68 = A3 extra transverse paper (322 mm by 445 mm)
132
- #69 = Japanese Double Postcard (200 mm x 148 mm)
131
+ #68 = A3 extra transverse paper (322 mm by 445 mm)
132
+ #69 = Japanese Double Postcard (200 mm x 148 mm)
133
133
  #70 = A6 (105 mm x 148 mm
134
134
  #71 = Japanese Envelope Kaku #2
135
135
  #72 = Japanese Envelope Kaku #3
@@ -142,7 +142,7 @@ module Axlsx
142
142
  #79 = B4 (JIS) Rotated (364 mm x 257 mm)
143
143
  #80 = B5 (JIS) Rotated (257 mm x 182 mm)
144
144
  #81 = Japanese Postcard Rotated (148 mm x 100 mm)
145
- #82 = Double Japanese Postcard Rotated (148 mm x 200 mm)
145
+ #82 = Double Japanese Postcard Rotated (148 mm x 200 mm)
146
146
  #83 = A6 Rotated (148 mm x 105 mm)
147
147
  #84 = Japanese Envelope Kaku #2 Rotated
148
148
  #85 = Japanese Envelope Kaku #3 Rotated
@@ -210,20 +210,20 @@ module Axlsx
210
210
  # @see scale
211
211
  def scale=(v); Axlsx::validate_scale_10_400(v); @scale = v; end
212
212
 
213
- # convenience method to achieve sanity when setting fit_to_width and fit_to_height
213
+ # convenience method to achieve sanity when setting fit_to_width and fit_to_height
214
214
  # as they both default to 1 if only their counterpart is specified.
215
215
  # @note This method will overwrite any value you explicitly set via the fit_to_height or fit_to_width methods.
216
- # @option options [Integer] width The number of pages to fit this worksheet on horizontally. Default 9999
217
- # @option options [Integer] height The number of pages to fit this worksheet on vertically. Default 9999
216
+ # @option options [Integer] width The number of pages to fit this worksheet on horizontally. Default 999
217
+ # @option options [Integer] height The number of pages to fit this worksheet on vertically. Default 999
218
218
  def fit_to(options={})
219
- self.fit_to_width = options[:width] || 9999
220
- self.fit_to_height = options[:height] || 9999
219
+ self.fit_to_width = options[:width] || 999
220
+ self.fit_to_height = options[:height] || 999
221
221
  [@fit_to_width, @fit_to_height]
222
222
  end
223
223
 
224
224
 
225
225
  # helper method for worksheet to determine if the page setup is configured for fit to page printing
226
- # We treat any page set up that has a value set for fit_to_width or fit_to_height value as fit_to_page.
226
+ # We treat any page set up that has a value set for fit_to_width or fit_to_height value as fit_to_page.
227
227
  # @return [Boolean]
228
228
  def fit_to_page?
229
229
  # is there some better what to express this?
@@ -234,9 +234,7 @@ module Axlsx
234
234
  # @param [String] str
235
235
  # @return [String]
236
236
  def to_xml_string(str = '')
237
- str << '<pageSetup '
238
- serialized_attributes str
239
- str << '/>'
237
+ serialized_tag('pageSetup', str)
240
238
  end
241
239
  end
242
240
  end
@@ -124,9 +124,7 @@ module Axlsx
124
124
  # @return [String]
125
125
  def to_xml_string(str = '')
126
126
  finalize
127
- str << '<pane '
128
- serialized_attributes str
129
- str << '/>'
127
+ serialized_tag 'pane', str
130
128
  end
131
129
  private
132
130
 
@@ -159,9 +159,9 @@ module Axlsx
159
159
  # @return [String]
160
160
  def to_xml_string(str = '')
161
161
  str << '<?xml version="1.0" encoding="UTF-8"?>'
162
- str << '<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '" dataOnRows="1" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" showMultipleLabel="0" showMemberPropertyTips="0" useAutoFormatting="1" indent="0" compact="0" compactData="0" gridDropZones="1" multipleFieldFilters="0">'
163
- str << '<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="' << ref << '"/>'
164
- str << '<pivotFields count="' << header_cells_count.to_s << '">'
162
+ str << ('<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '" dataOnRows="1" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" showMultipleLabel="0" showMemberPropertyTips="0" useAutoFormatting="1" indent="0" compact="0" compactData="0" gridDropZones="1" multipleFieldFilters="0">')
163
+ str << ( '<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="' << ref << '"/>')
164
+ str << ( '<pivotFields count="' << header_cells_count.to_s << '">')
165
165
  header_cell_values.each do |cell_value|
166
166
  str << pivot_field_for(cell_value)
167
167
  end
@@ -170,12 +170,12 @@ module Axlsx
170
170
  str << '<rowFields count="1"><field x="-2"/></rowFields>'
171
171
  str << '<rowItems count="2"><i><x/></i> <i i="1"><x v="1"/></i></rowItems>'
172
172
  else
173
- str << '<rowFields count="' << rows.size.to_s << '">'
173
+ str << ('<rowFields count="' << rows.size.to_s << '">')
174
174
  rows.each do |row_value|
175
- str << '<field x="' << header_index_of(row_value).to_s << '"/>'
175
+ str << ('<field x="' << header_index_of(row_value).to_s << '"/>')
176
176
  end
177
177
  str << '</rowFields>'
178
- str << '<rowItems count="' << rows.size.to_s << '">'
178
+ str << ('<rowItems count="' << rows.size.to_s << '">')
179
179
  rows.size.times do |i|
180
180
  str << '<i/>'
181
181
  end
@@ -184,16 +184,16 @@ module Axlsx
184
184
  if columns.empty?
185
185
  str << '<colItems count="1"><i/></colItems>'
186
186
  else
187
- str << '<colFields count="' << columns.size.to_s << '">'
187
+ str << ('<colFields count="' << columns.size.to_s << '">')
188
188
  columns.each do |column_value|
189
- str << '<field x="' << header_index_of(column_value).to_s << '"/>'
189
+ str << ('<field x="' << header_index_of(column_value).to_s << '"/>')
190
190
  end
191
191
  str << '</colFields>'
192
192
  end
193
193
  unless pages.empty?
194
- str << '<pageFields count="' << pages.size.to_s << '">'
194
+ str << ('<pageFields count="' << pages.size.to_s << '">')
195
195
  pages.each do |page_value|
196
- str << '<pageField fld="' << header_index_of(page_value).to_s << '"/>'
196
+ str << ('<pageField fld="' << header_index_of(page_value).to_s << '"/>')
197
197
  end
198
198
  str << '</pageFields>'
199
199
  end
@@ -243,31 +243,24 @@ module Axlsx
243
243
 
244
244
  def pivot_field_for(cell_ref)
245
245
  if rows.include? cell_ref
246
- '<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
247
- '<items count="1"><item t="default"/></items>' <<
248
- '</pivotField>'
246
+ '<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '<items count="1"><item t="default"/></items>' + '</pivotField>'
249
247
  elsif columns.include? cell_ref
250
- '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
251
- '<items count="1"><item t="default"/></items>' <<
252
- '</pivotField>'
248
+ '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '<items count="1"><item t="default"/></items>' + '</pivotField>'
253
249
  elsif pages.include? cell_ref
254
- '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
255
- '<items count="1"><item t="default"/></items>' <<
256
- '</pivotField>'
250
+ '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '<items count="1"><item t="default"/></items>' + '</pivotField>'
257
251
  elsif data_refs.include? cell_ref
258
- '<pivotField dataField="1" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
259
- '</pivotField>'
252
+ '<pivotField dataField="1" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '</pivotField>'
260
253
  else
261
- '<pivotField compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
262
- '</pivotField>'
254
+ '<pivotField compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '</pivotField>'
263
255
  end
264
256
  end
257
+
265
258
  def data_refs
266
259
  data.map { |hash| hash[:ref] }
267
260
  end
261
+
268
262
  def header_range
269
263
  range.gsub(/^(\w+?)(\d+)\:(\w+?)\d+$/, '\1\2:\3\2')
270
264
  end
271
-
272
265
  end
273
266
  end
@@ -47,13 +47,13 @@ module Axlsx
47
47
  # @return [String]
48
48
  def to_xml_string(str = '')
49
49
  str << '<?xml version="1.0" encoding="UTF-8"?>'
50
- str << '<pivotCacheDefinition xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '" invalid="1" refreshOnLoad="1" recordCount="0">'
50
+ str << ('<pivotCacheDefinition xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '" invalid="1" refreshOnLoad="1" recordCount="0">')
51
51
  str << '<cacheSource type="worksheet">'
52
- str << '<worksheetSource ref="' << pivot_table.range << '" sheet="' << pivot_table.data_sheet.name << '"/>'
52
+ str << ( '<worksheetSource ref="' << pivot_table.range << '" sheet="' << pivot_table.data_sheet.name << '"/>')
53
53
  str << '</cacheSource>'
54
- str << '<cacheFields count="' << pivot_table.header_cells_count.to_s << '">'
54
+ str << ( '<cacheFields count="' << pivot_table.header_cells_count.to_s << '">')
55
55
  pivot_table.header_cells.each do |cell|
56
- str << '<cacheField name="' << cell.value << '" numFmtId="0">'
56
+ str << ( '<cacheField name="' << cell.value << '" numFmtId="0">')
57
57
  str << '<sharedItems count="0">'
58
58
  str << '</sharedItems>'
59
59
  str << '</cacheField>'
@@ -33,9 +33,7 @@ module Axlsx
33
33
  # @param [String] str
34
34
  # @return [String]
35
35
  def to_xml_string(str = '')
36
- str << '<printOptions '
37
- serialized_attributes str
38
- str << '/>'
36
+ serialized_tag 'printOptions', str
39
37
  end
40
38
  end
41
39
  end
@@ -41,9 +41,7 @@ module Axlsx
41
41
  # our output to that object. Use this - it helps limit the number of
42
42
  # objects created during serialization
43
43
  def to_xml_string(str="")
44
- str << '<protectedRange '
45
- serialized_attributes str
46
- str << '/>'
44
+ serialized_tag 'protectedRange', str
47
45
  end
48
46
  end
49
47
  end
@@ -20,7 +20,7 @@ module Axlsx
20
20
  elsif cells.is_a?(SimpleTypedList) || cells.is_a?(Array)
21
21
  Axlsx::cell_range(cells, false)
22
22
  end
23
- @list << ProtectedRange.new(:sqref => sqref, :name => "Range#{size}")
23
+ self << ProtectedRange.new(:sqref => sqref, :name => "Range#{size}")
24
24
  last
25
25
  end
26
26
 
@@ -0,0 +1,35 @@
1
+ module Axlsx
2
+ class RichText < SimpleTypedList
3
+ def initialize(text = nil, options={})
4
+ super(RichTextRun)
5
+ add_run(text, options) unless text.nil?
6
+ yield self if block_given?
7
+ end
8
+
9
+ attr_reader :cell
10
+
11
+ def cell=(cell)
12
+ @cell = cell
13
+ each { |run| run.cell = cell }
14
+ end
15
+
16
+ def autowidth
17
+ widtharray = [0] # Are arrays the best way of solving this problem?
18
+ each { |run| run.autowidth(widtharray) }
19
+ widtharray.max
20
+ end
21
+
22
+ def add_run(text, options={})
23
+ self << RichTextRun.new(text, options)
24
+ end
25
+
26
+ def runs
27
+ self
28
+ end
29
+
30
+ def to_xml_string(str='')
31
+ each{ |run| run.to_xml_string(str) }
32
+ str
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,254 @@
1
+ module Axlsx
2
+ class RichTextRun
3
+
4
+ include Axlsx::OptionsParser
5
+
6
+ attr_reader :value
7
+
8
+ INLINE_STYLES = [:font_name, :charset,
9
+ :family, :b, :i, :strike, :outline,
10
+ :shadow, :condense, :extend, :u,
11
+ :vertAlign, :sz, :color, :scheme].freeze
12
+
13
+ def initialize(value, options={})
14
+ self.value = value
15
+ parse_options(options)
16
+ end
17
+
18
+ def value=(value)
19
+ @value = value
20
+ end
21
+
22
+ attr_accessor :cell
23
+
24
+ # The inline font_name property for the cell
25
+ # @return [String]
26
+ attr_reader :font_name
27
+ # @see font_name
28
+ def font_name=(v) set_run_style :validate_string, :font_name, v; end
29
+
30
+ # The inline charset property for the cell
31
+ # As far as I can tell, this is pretty much ignored. However, based on the spec it should be one of the following:
32
+ # 0  ANSI_CHARSET
33
+ # 1 DEFAULT_CHARSET
34
+ # 2 SYMBOL_CHARSET
35
+ # 77 MAC_CHARSET
36
+ # 128 SHIFTJIS_CHARSET
37
+ # 129  HANGUL_CHARSET
38
+ # 130  JOHAB_CHARSET
39
+ # 134  GB2312_CHARSET
40
+ # 136  CHINESEBIG5_CHARSET
41
+ # 161  GREEK_CHARSET
42
+ # 162  TURKISH_CHARSET
43
+ # 163  VIETNAMESE_CHARSET
44
+ # 177  HEBREW_CHARSET
45
+ # 178  ARABIC_CHARSET
46
+ # 186  BALTIC_CHARSET
47
+ # 204  RUSSIAN_CHARSET
48
+ # 222  THAI_CHARSET
49
+ # 238  EASTEUROPE_CHARSET
50
+ # 255  OEM_CHARSET
51
+ # @return [String]
52
+ attr_reader :charset
53
+ # @see charset
54
+ def charset=(v) set_run_style :validate_unsigned_int, :charset, v; end
55
+
56
+ # The inline family property for the cell
57
+ # @return [Integer]
58
+ # 1 Roman
59
+ # 2 Swiss
60
+ # 3 Modern
61
+ # 4 Script
62
+ # 5 Decorative
63
+ attr_reader :family
64
+ # @see family
65
+ def family=(v)
66
+ set_run_style :validate_family, :family, v.to_i
67
+ end
68
+
69
+ # The inline bold property for the cell
70
+ # @return [Boolean]
71
+ attr_reader :b
72
+ # @see b
73
+ def b=(v) set_run_style :validate_boolean, :b, v; end
74
+
75
+ # The inline italic property for the cell
76
+ # @return [Boolean]
77
+ attr_reader :i
78
+ # @see i
79
+ def i=(v) set_run_style :validate_boolean, :i, v; end
80
+
81
+ # The inline strike property for the cell
82
+ # @return [Boolean]
83
+ attr_reader :strike
84
+ # @see strike
85
+ def strike=(v) set_run_style :validate_boolean, :strike, v; end
86
+
87
+ # The inline outline property for the cell
88
+ # @return [Boolean]
89
+ attr_reader :outline
90
+ # @see outline
91
+ def outline=(v) set_run_style :validate_boolean, :outline, v; end
92
+
93
+ # The inline shadow property for the cell
94
+ # @return [Boolean]
95
+ attr_reader :shadow
96
+ # @see shadow
97
+ def shadow=(v) set_run_style :validate_boolean, :shadow, v; end
98
+
99
+ # The inline condense property for the cell
100
+ # @return [Boolean]
101
+ attr_reader :condense
102
+ # @see condense
103
+ def condense=(v) set_run_style :validate_boolean, :condense, v; end
104
+
105
+ # The inline extend property for the cell
106
+ # @return [Boolean]
107
+ attr_reader :extend
108
+ # @see extend
109
+ def extend=(v) set_run_style :validate_boolean, :extend, v; end
110
+
111
+ # The inline underline property for the cell.
112
+ # It must be one of :none, :single, :double, :singleAccounting, :doubleAccounting, true
113
+ # @return [Boolean]
114
+ # @return [String]
115
+ # @note true is for backwards compatability and is reassigned to :single
116
+ attr_reader :u
117
+ # @see u
118
+ def u=(v)
119
+ v = :single if (v == true || v == 1 || v == :true || v == 'true')
120
+ set_run_style :validate_cell_u, :u, v
121
+ end
122
+
123
+ # The inline color property for the cell
124
+ # @return [Color]
125
+ attr_reader :color
126
+ # @param [String] v The 8 character representation for an rgb color #FFFFFFFF"
127
+ def color=(v)
128
+ @color = v.is_a?(Color) ? v : Color.new(:rgb=>v)
129
+ end
130
+
131
+ # The inline sz property for the cell
132
+ # @return [Inteter]
133
+ attr_reader :sz
134
+ # @see sz
135
+ def sz=(v) set_run_style :validate_unsigned_int, :sz, v; end
136
+
137
+ # The inline vertical alignment property for the cell
138
+ # this must be one of [:baseline, :subscript, :superscript]
139
+ # @return [Symbol]
140
+ attr_reader :vertAlign
141
+ # @see vertAlign
142
+ def vertAlign=(v)
143
+ RestrictionValidator.validate :cell_vertAlign, [:baseline, :subscript, :superscript], v
144
+ set_run_style nil, :vertAlign, v
145
+ end
146
+
147
+ # The inline scheme property for the cell
148
+ # this must be one of [:none, major, minor]
149
+ # @return [Symbol]
150
+ attr_reader :scheme
151
+ # @see scheme
152
+ def scheme=(v)
153
+ RestrictionValidator.validate :cell_scheme, [:none, :major, :minor], v
154
+ set_run_style nil, :scheme, v
155
+ end
156
+
157
+ # The Shared Strings Table index for this cell
158
+ # @return [Integer]
159
+ attr_reader :ssti
160
+
161
+ # @return [Integer] The cellXfs item index applied to this cell.
162
+ # @raise [ArgumentError] Invalid cellXfs id if the value provided is not within cellXfs items range.
163
+ def style=(v)
164
+ Axlsx::validate_unsigned_int(v)
165
+ count = styles.cellXfs.size
166
+ raise ArgumentError, "Invalid cellXfs id" unless v < count
167
+ @style = v
168
+ end
169
+
170
+ def autowidth(widtharray)
171
+ return if value.nil?
172
+ if styles.cellXfs[style].alignment && styles.cellXfs[style].alignment.wrap_text
173
+ first = true
174
+ value.to_s.split(/\r?\n/, -1).each do |line|
175
+ if first
176
+ first = false
177
+ else
178
+ widtharray << 0
179
+ end
180
+ widtharray[-1] += string_width(line, font_size)
181
+ end
182
+ else
183
+ widtharray[-1] += string_width(value.to_s, font_size)
184
+ end
185
+ widtharray
186
+ end
187
+
188
+ # Utility method for setting inline style attributes
189
+ def set_run_style(validator, attr, value)
190
+ return unless INLINE_STYLES.include?(attr.to_sym)
191
+ Axlsx.send(validator, value) unless validator.nil?
192
+ self.instance_variable_set :"@#{attr.to_s}", value
193
+ end
194
+
195
+ def to_xml_string(str = '')
196
+ valid = RichTextRun::INLINE_STYLES
197
+ data = Hash[self.instance_values.map{ |k, v| [k.to_sym, v] }]
198
+ data = data.select { |key, value| valid.include?(key) && !value.nil? }
199
+
200
+ str << '<r><rPr>'
201
+ data.keys.each do |key|
202
+ case key
203
+ when :font_name
204
+ str << ('<rFont val="' << font_name << '"/>')
205
+ when :color
206
+ str << data[key].to_xml_string
207
+ else
208
+ str << ('<' << key.to_s << ' val="' << xml_value(data[key]) << '"/>')
209
+ end
210
+ end
211
+ clean_value = Axlsx::trust_input ? @value.to_s : ::CGI.escapeHTML(Axlsx::sanitize(@value.to_s))
212
+ str << ('</rPr><t>' << clean_value << '</t></r>')
213
+ end
214
+
215
+ private
216
+
217
+ # Returns the width of a string according to the current style
218
+ # This is still not perfect...
219
+ # - scaling is not linear as font sizes increase
220
+ def string_width(string, font_size)
221
+ font_scale = font_size / 10.0
222
+ string.count(Worksheet::THIN_CHARS) * font_scale
223
+ end
224
+
225
+ # we scale the font size if bold style is applied to either the style font or
226
+ # the cell itself. Yes, it is a bit of a hack, but it is much better than using
227
+ # imagemagick and loading metrics for every character.
228
+ def font_size
229
+ return sz if sz
230
+ font = styles.fonts[styles.cellXfs[style].fontId] || styles.fonts[0]
231
+ (font.b || (defined?(@b) && @b)) ? (font.sz * 1.5) : font.sz
232
+ end
233
+
234
+ def style
235
+ cell.style
236
+ end
237
+
238
+ def styles
239
+ cell.row.worksheet.styles
240
+ end
241
+
242
+ # Converts the value to the correct XML representation (fixes issues with
243
+ # Numbers)
244
+ def xml_value value
245
+ if value == true
246
+ 1
247
+ elsif value == false
248
+ 0
249
+ else
250
+ value
251
+ end.to_s
252
+ end
253
+ end
254
+ end