write_xlsx 0.81.1 → 0.83.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -0
  3. data/Changes +20 -0
  4. data/README.md +3 -2
  5. data/examples/chart_combined.rb +107 -0
  6. data/examples/chart_data_table.rb +1 -1
  7. data/examples/chart_pareto.rb +82 -0
  8. data/lib/write_xlsx/chart.rb +115 -42
  9. data/lib/write_xlsx/chart/axis.rb +5 -1
  10. data/lib/write_xlsx/chart/bar.rb +13 -0
  11. data/lib/write_xlsx/chart/pie.rb +7 -0
  12. data/lib/write_xlsx/chart/scatter.rb +25 -57
  13. data/lib/write_xlsx/format.rb +40 -0
  14. data/lib/write_xlsx/package/app.rb +39 -1
  15. data/lib/write_xlsx/package/comments.rb +1 -5
  16. data/lib/write_xlsx/package/content_types.rb +48 -13
  17. data/lib/write_xlsx/package/core.rb +14 -12
  18. data/lib/write_xlsx/package/packager.rb +17 -41
  19. data/lib/write_xlsx/package/styles.rb +215 -256
  20. data/lib/write_xlsx/package/table.rb +5 -7
  21. data/lib/write_xlsx/package/xml_writer_simple.rb +2 -0
  22. data/lib/write_xlsx/sheets.rb +2 -2
  23. data/lib/write_xlsx/utility.rb +17 -2
  24. data/lib/write_xlsx/version.rb +1 -1
  25. data/lib/write_xlsx/workbook.rb +44 -2
  26. data/lib/write_xlsx/worksheet.rb +26 -17
  27. data/lib/write_xlsx/worksheet/page_setup.rb +12 -6
  28. data/test/chart/test_write_style.rb +2 -2
  29. data/test/helper.rb +3 -0
  30. data/test/package/app/test_app01.rb +1 -1
  31. data/test/package/app/test_app02.rb +1 -1
  32. data/test/package/app/test_app03.rb +1 -1
  33. data/test/package/content_types/test_content_types.rb +1 -1
  34. data/test/package/content_types/test_write_default.rb +1 -1
  35. data/test/package/content_types/test_write_override.rb +1 -1
  36. data/test/perl_output/chart_combined.xlsx +0 -0
  37. data/test/perl_output/chart_pareto.xlsx +0 -0
  38. data/test/regression/test_button07.rb +5 -2
  39. data/test/regression/test_button13.rb +34 -0
  40. data/test/regression/test_button14.rb +31 -0
  41. data/test/regression/test_chart_column11.rb +45 -0
  42. data/test/regression/test_chart_column12.rb +45 -0
  43. data/test/regression/test_chart_combined01.rb +37 -0
  44. data/test/regression/test_chart_combined02.rb +43 -0
  45. data/test/regression/test_chart_combined03.rb +45 -0
  46. data/test/regression/test_chart_combined04.rb +47 -0
  47. data/test/regression/test_chart_combined05.rb +49 -0
  48. data/test/regression/test_chart_combined06.rb +49 -0
  49. data/test/regression/test_chart_combined07.rb +53 -0
  50. data/test/regression/test_chart_combined08.rb +65 -0
  51. data/test/regression/test_chart_data_labels24.rb +50 -0
  52. data/test/regression/test_chart_date05.rb +57 -0
  53. data/test/regression/test_chart_format20.rb +55 -0
  54. data/test/regression/test_format11.rb +28 -0
  55. data/test/regression/test_format12.rb +41 -0
  56. data/test/regression/test_landscape01.rb +27 -0
  57. data/test/regression/test_quote_name04.rb +40 -0
  58. data/test/regression/test_set_start_page01.rb +4 -7
  59. data/test/regression/test_set_start_page02.rb +33 -0
  60. data/test/regression/test_set_start_page03.rb +33 -0
  61. data/test/regression/test_table17.rb +70 -0
  62. data/test/regression/xlsx_files/chart_column11.xlsx +0 -0
  63. data/test/regression/xlsx_files/chart_column12.xlsx +0 -0
  64. data/test/regression/xlsx_files/chart_combined01.xlsx +0 -0
  65. data/test/regression/xlsx_files/chart_combined02.xlsx +0 -0
  66. data/test/regression/xlsx_files/chart_combined03.xlsx +0 -0
  67. data/test/regression/xlsx_files/chart_combined04.xlsx +0 -0
  68. data/test/regression/xlsx_files/chart_combined05.xlsx +0 -0
  69. data/test/regression/xlsx_files/chart_combined06.xlsx +0 -0
  70. data/test/regression/xlsx_files/chart_combined07.xlsx +0 -0
  71. data/test/regression/xlsx_files/chart_combined08.xlsx +0 -0
  72. data/test/regression/xlsx_files/chart_date05.xlsx +0 -0
  73. data/test/regression/xlsx_files/chart_format20.xlsx +0 -0
  74. data/test/regression/xlsx_files/format11.xlsx +0 -0
  75. data/test/regression/xlsx_files/format12.xlsx +0 -0
  76. data/test/regression/xlsx_files/landscape01.xlsx +0 -0
  77. data/test/regression/xlsx_files/quote_name04.xlsx +0 -0
  78. data/test/regression/xlsx_files/set_start_page01.xlsx +0 -0
  79. data/test/regression/xlsx_files/set_start_page02.xlsx +0 -0
  80. data/test/regression/xlsx_files/set_start_page03.xlsx +0 -0
  81. data/test/regression/xlsx_files/table17.xlsx +0 -0
  82. data/test/test_example_match.rb +172 -0
  83. data/write_xlsx.gemspec +1 -0
  84. metadata +106 -3
@@ -136,37 +136,25 @@ def write_shared_strings_file
136
136
  # Write the app.xml file.
137
137
  #
138
138
  def write_app_file
139
- dir = @package_dir
140
- properties = @workbook.doc_properties
141
- app = Package::App.new
142
-
143
- FileUtils.mkdir_p("#{@package_dir}/docProps")
139
+ app = Package::App.new(@workbook)
144
140
 
145
141
  # Add the Worksheet heading pairs.
146
- app.add_heading_pair(['Worksheets', @workbook.worksheets.reject {|s| s.is_chartsheet?}.count])
147
-
142
+ app.add_worksheet_heading_pairs
148
143
  # Add the Chartsheet heading pairs.
149
- app.add_heading_pair(['Charts', @workbook.chartsheet_count])
144
+ app.add_chartsheet_heading_pairs
150
145
 
151
146
  # Add the Worksheet parts.
152
- @workbook.worksheets.reject { |sheet| sheet.is_chartsheet? }.
153
- each { |sheet| app.add_part_name(sheet.name) }
154
-
147
+ app.add_worksheet_part_names
155
148
  # Add the Chartsheet parts.
156
- @workbook.worksheets.select { |sheet| sheet.is_chartsheet? }.
157
- each { |sheet| app.add_part_name(sheet.name) }
158
-
149
+ app.add_chartsheet_part_names
159
150
  # Add the Named Range heading pairs.
160
- range_count = @workbook.named_ranges.size
161
- if range_count != 0
162
- app.add_heading_pair([ 'Named Ranges', range_count ])
163
- end
164
-
151
+ app.add_named_range_heading_pairs
165
152
  # Add the Named Ranges parts.
166
- @workbook.named_ranges.each { |named_range| app.add_part_name(named_range) }
153
+ app.add_named_ranges_parts
167
154
 
168
- app.set_properties(properties)
155
+ app.set_properties(@workbook.doc_properties)
169
156
 
157
+ FileUtils.mkdir_p("#{@package_dir}/docProps")
170
158
  app.set_xml_writer("#{@package_dir}/docProps/app.xml")
171
159
  app.assemble_xml_file
172
160
  end
@@ -188,30 +176,18 @@ def write_core_file
188
176
  # Write the ContentTypes.xml file.
189
177
  #
190
178
  def write_content_types_file
191
- content = Package::ContentTypes.new
192
-
193
- content.add_image_types(@workbook.image_types)
194
- @workbook.worksheets.reject { |sheet| sheet.is_chartsheet? }.
195
- each_with_index do |sheet, index|
196
- content.add_worksheet_name("sheet#{index+1}")
197
- end
198
- @workbook.worksheets.select { |sheet| sheet.is_chartsheet? }.
199
- each_with_index do |sheet, index|
200
- content.add_chartsheet_name("sheet#{index+1}")
201
- end
202
-
203
- (1 .. @workbook.charts.size).each { |i| content.add_chart_name("chart#{i}") }
204
- (1 .. @workbook.drawings.size).each { |i| content.add_drawing_name("drawing#{i}") }
179
+ content = Package::ContentTypes.new(@workbook)
205
180
 
181
+ content.add_image_types
182
+ content.add_worksheet_names
183
+ content.add_chartsheet_names
184
+ content.add_chart_names
185
+ content.add_drawing_names
206
186
  content.add_vml_name if @workbook.num_vml_files > 0
207
-
208
- (1 .. @table_count).each { |i| content.add_table_name("table#{i}") }
209
-
210
- (1 .. @workbook.num_comment_files).each { |i| content.add_comment_name("comments#{i}") }
211
-
187
+ content.add_table_names(@table_count)
188
+ content.add_comment_names
212
189
  # Add the sharedString rel if there is string data in the workbook.
213
190
  content.add_shared_strings unless @workbook.shared_strings_empty?
214
-
215
191
  # Add vbaProject if present.
216
192
  content.add_vba_project if @workbook.vba_project
217
193
 
@@ -26,18 +26,7 @@ def set_xml_writer(filename)
26
26
 
27
27
  def assemble_xml_file
28
28
  write_xml_declaration do
29
- write_style_sheet do
30
- write_num_fmts
31
- write_fonts
32
- write_fills
33
- write_borders
34
- write_cell_style_xfs
35
- write_cell_xfs
36
- write_cell_styles
37
- write_dxfs
38
- write_table_styles
39
- write_colors
40
- end
29
+ write_style_sheet { write_style_sheet_base }
41
30
  end
42
31
  end
43
32
 
@@ -71,9 +60,7 @@ def palette_color(index)
71
60
  # Write the <styleSheet> element.
72
61
  #
73
62
  def write_style_sheet
74
- xmlns = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'
75
-
76
- attributes = [ ['xmlns', xmlns] ]
63
+ attributes = [ ['xmlns', XMLWriterSimple::XMLNS] ]
77
64
 
78
65
  @writer.tag_elements('styleSheet', attributes) { yield }
79
66
  end
@@ -98,57 +85,51 @@ def write_num_fmts
98
85
  end
99
86
  end
100
87
 
88
+ FORMAT_CODES = {
89
+ 0 => 'General',
90
+ 1 => '0',
91
+ 2 => '0.00',
92
+ 3 => '#,##0',
93
+ 4 => '#,##0.00',
94
+ 5 => '($#,##0_);($#,##0)',
95
+ 6 => '($#,##0_);[Red]($#,##0)',
96
+ 7 => '($#,##0.00_);($#,##0.00)',
97
+ 8 => '($#,##0.00_);[Red]($#,##0.00)',
98
+ 9 => '0%',
99
+ 10 => '0.00%',
100
+ 11 => '0.00E+00',
101
+ 12 => '# ?/?',
102
+ 13 => '# ??/??',
103
+ 14 => 'm/d/yy',
104
+ 15 => 'd-mmm-yy',
105
+ 16 => 'd-mmm',
106
+ 17 => 'mmm-yy',
107
+ 18 => 'h:mm AM/PM',
108
+ 19 => 'h:mm:ss AM/PM',
109
+ 20 => 'h:mm',
110
+ 21 => 'h:mm:ss',
111
+ 22 => 'm/d/yy h:mm',
112
+ 37 => '(#,##0_);(#,##0)',
113
+ 38 => '(#,##0_);[Red](#,##0)',
114
+ 39 => '(#,##0.00_);(#,##0.00)',
115
+ 40 => '(#,##0.00_);[Red](#,##0.00)',
116
+ 41 => '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)',
117
+ 42 => '_($* #,##0_);_($* (#,##0);_($* "-"_);_(@_)',
118
+ 43 => '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)',
119
+ 44 => '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)',
120
+ 45 => 'mm:ss',
121
+ 46 => '[h]:mm:ss',
122
+ 47 => 'mm:ss.0',
123
+ 48 => '##0.0E+0',
124
+ 49 => '@'
125
+ }
126
+
101
127
  #
102
128
  # Write the <numFmt> element.
103
129
  #
104
130
  def write_num_fmt(num_fmt_id, format_code)
105
- format_codes = {
106
- 0 => 'General',
107
- 1 => '0',
108
- 2 => '0.00',
109
- 3 => '#,##0',
110
- 4 => '#,##0.00',
111
- 5 => '($#,##0_);($#,##0)',
112
- 6 => '($#,##0_);[Red]($#,##0)',
113
- 7 => '($#,##0.00_);($#,##0.00)',
114
- 8 => '($#,##0.00_);[Red]($#,##0.00)',
115
- 9 => '0%',
116
- 10 => '0.00%',
117
- 11 => '0.00E+00',
118
- 12 => '# ?/?',
119
- 13 => '# ??/??',
120
- 14 => 'm/d/yy',
121
- 15 => 'd-mmm-yy',
122
- 16 => 'd-mmm',
123
- 17 => 'mmm-yy',
124
- 18 => 'h:mm AM/PM',
125
- 19 => 'h:mm:ss AM/PM',
126
- 20 => 'h:mm',
127
- 21 => 'h:mm:ss',
128
- 22 => 'm/d/yy h:mm',
129
- 37 => '(#,##0_);(#,##0)',
130
- 38 => '(#,##0_);[Red](#,##0)',
131
- 39 => '(#,##0.00_);(#,##0.00)',
132
- 40 => '(#,##0.00_);[Red](#,##0.00)',
133
- 41 => '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)',
134
- 42 => '_($* #,##0_);_($* (#,##0);_($* "-"_);_(@_)',
135
- 43 => '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)',
136
- 44 => '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)',
137
- 45 => 'mm:ss',
138
- 46 => '[h]:mm:ss',
139
- 47 => 'mm:ss.0',
140
- 48 => '##0.0E+0',
141
- 49 => '@'
142
- }
143
-
144
131
  # Set the format code for built-in number formats.
145
- if num_fmt_id < 164
146
- if format_codes[num_fmt_id]
147
- format_code = format_codes[num_fmt_id]
148
- else
149
- format_code = 'General'
150
- end
151
- end
132
+ format_code = FORMAT_CODES[num_fmt_id] || 'General' if num_fmt_id < 164
152
133
 
153
134
  attributes = [
154
135
  ['numFmtId', num_fmt_id],
@@ -163,9 +144,13 @@ def write_num_fmt(num_fmt_id, format_code)
163
144
  #
164
145
  def write_fonts
165
146
  write_format_elements('fonts', @font_count) do
166
- @xf_formats.each do |format|
167
- format.write_font(@writer, self) if format.has_font?
168
- end
147
+ write_font_base
148
+ end
149
+ end
150
+
151
+ def write_font_base
152
+ @xf_formats.each do |format|
153
+ format.write_font(@writer, self) if format.has_font?
169
154
  end
170
155
  end
171
156
 
@@ -182,19 +167,21 @@ def write_color(name, value)
182
167
  # Write the <fills> element.
183
168
  #
184
169
  def write_fills
185
- count = @fill_count
186
-
187
- attributes = [ ['count', count] ]
170
+ attributes = [ ['count', @fill_count] ]
188
171
 
189
172
  @writer.tag_elements('fills', attributes) do
190
- # Write the default fill element.
191
- write_default_fill('none')
192
- write_default_fill('gray125')
173
+ write_fills_base
174
+ end
175
+ end
193
176
 
194
- # Write the fill elements for format objects that have them.
195
- @xf_formats.each do |format|
196
- write_fill(format) if format.has_fill?
197
- end
177
+ def write_fills_base
178
+ # Write the default fill element.
179
+ write_default_fill('none')
180
+ write_default_fill('gray125')
181
+
182
+ # Write the fill elements for format objects that have them.
183
+ @xf_formats.each do |format|
184
+ write_fill(format) if format.has_fill?
198
185
  end
199
186
  end
200
187
 
@@ -207,11 +194,65 @@ def write_default_fill(pattern_type)
207
194
  end
208
195
  end
209
196
 
197
+ PATTERNS = %w(
198
+ none
199
+ solid
200
+ mediumGray
201
+ darkGray
202
+ lightGray
203
+ darkHorizontal
204
+ darkVertical
205
+ darkDown
206
+ darkUp
207
+ darkGrid
208
+ darkTrellis
209
+ lightHorizontal
210
+ lightVertical
211
+ lightDown
212
+ lightUp
213
+ lightGrid
214
+ lightTrellis
215
+ gray125
216
+ gray0625
217
+ )
218
+
210
219
  #
211
220
  # Write the <fill> element.
212
221
  #
213
222
  def write_fill(format, dxf_format = nil)
214
- pattern = format.pattern
223
+ @writer.tag_elements('fill' ) do
224
+ write_fill_base(format, dxf_format)
225
+ end
226
+ end
227
+
228
+ def write_fill_base(format, dxf_format)
229
+ # The "none" pattern is handled differently for dxf formats.
230
+ if dxf_format && format.pattern <= 1
231
+ attributes = []
232
+ else
233
+ attributes = [ ['patternType', PATTERNS[format.pattern]] ]
234
+ end
235
+
236
+ @writer.tag_elements('patternFill', attributes) do
237
+ write_pattern_fill(format, dxf_format)
238
+ end
239
+ end
240
+
241
+ def write_pattern_fill(format, dxf_format)
242
+ bg_color, fg_color = bg_and_fg_color(format, dxf_format)
243
+
244
+ if fg_color && fg_color != 0
245
+ @writer.empty_tag('fgColor', [ ['rgb', palette_color(fg_color)] ])
246
+ end
247
+
248
+ if bg_color && bg_color != 0
249
+ @writer.empty_tag('bgColor', [ ['rgb', palette_color(bg_color)] ])
250
+ else
251
+ @writer.empty_tag('bgColor', [ ['indexed', 64] ]) if !dxf_format
252
+ end
253
+ end
254
+
255
+ def bg_and_fg_color(format, dxf_format)
215
256
  bg_color = format.bg_color
216
257
  fg_color = format.fg_color
217
258
 
@@ -222,50 +263,7 @@ def write_fill(format, dxf_format = nil)
222
263
  fg_color = format.dxf_fg_color
223
264
  end
224
265
 
225
- patterns = %w(
226
- none
227
- solid
228
- mediumGray
229
- darkGray
230
- lightGray
231
- darkHorizontal
232
- darkVertical
233
- darkDown
234
- darkUp
235
- darkGrid
236
- darkTrellis
237
- lightHorizontal
238
- lightVertical
239
- lightDown
240
- lightUp
241
- lightGrid
242
- lightTrellis
243
- gray125
244
- gray0625
245
- )
246
-
247
- @writer.tag_elements('fill' ) do
248
- # The "none" pattern is handled differently for dxf formats.
249
- if dxf_format && format.pattern <= 1
250
- attributes = []
251
- else
252
- attributes = [ ['patternType', patterns[format.pattern]] ]
253
- end
254
-
255
- @writer.tag_elements('patternFill', attributes) do
256
- if fg_color && fg_color != 0
257
- fg_color = palette_color(fg_color)
258
- @writer.empty_tag('fgColor', [ ['rgb', fg_color] ])
259
- end
260
-
261
- if bg_color && bg_color != 0
262
- bg_color = palette_color(bg_color)
263
- @writer.empty_tag('bgColor', [ ['rgb', bg_color] ])
264
- else
265
- @writer.empty_tag('bgColor', [ ['indexed', 64] ]) if !dxf_format
266
- end
267
- end
268
- end
266
+ [bg_color, fg_color]
269
267
  end
270
268
 
271
269
  #
@@ -273,9 +271,13 @@ def write_fill(format, dxf_format = nil)
273
271
  #
274
272
  def write_borders
275
273
  write_format_elements('borders', @border_count) do
276
- @xf_formats.each do |format|
277
- write_border(format) if format.has_border?
278
- end
274
+ write_borders_base
275
+ end
276
+ end
277
+
278
+ def write_borders_base
279
+ @xf_formats.each do |format|
280
+ write_border(format) if format.has_border?
279
281
  end
280
282
  end
281
283
 
@@ -292,41 +294,52 @@ def write_format_elements(elements, count)
292
294
  # Write the <border> element.
293
295
  #
294
296
  def write_border(format, dxf_format = nil)
295
- attributes = []
296
-
297
- # Diagonal borders add attributes to the <border> element.
298
- if format.diag_type == 1
299
- attributes << ['diagonalUp', 1]
300
- elsif format.diag_type == 2
301
- attributes << ['diagonalDown', 1]
302
- elsif format.diag_type == 3
303
- attributes << ['diagonalUp', 1]
304
- attributes << ['diagonalDown', 1]
297
+ # Write the start border tag.
298
+ @writer.tag_elements('border', format.border_attributes) do
299
+ write_border_base(format, dxf_format)
305
300
  end
301
+ end
306
302
 
307
- # Ensure that a default diag border is set if the diag type is set.
308
- format.diag_border = 1 if format.diag_type != 0 && format.diag_border == 0
303
+ def write_border_base(format, dxf_format)
304
+ # Write the <border> sub elements.
305
+ write_border_sub_elements(format)
309
306
 
310
- # Write the start border tag.
311
- @writer.tag_elements('border', attributes) do
312
- # Write the <border> sub elements.
313
- write_sub_border('left', format.left, format.left_color)
314
- write_sub_border('right', format.right, format.right_color)
315
- write_sub_border('top', format.top, format.top_color)
316
- write_sub_border('bottom', format.bottom, format.bottom_color)
317
-
318
- # Condition DXF formats don't allow diagonal borders
319
- if !dxf_format
320
- write_sub_border('diagonal', format.diag_border, format.diag_color)
321
- end
307
+ # Condition DXF formats don't allow diagonal borders
308
+ if dxf_format
309
+ write_sub_border('vertical')
310
+ write_sub_border('horizontal')
311
+ else
312
+ # Ensure that a default diag border is set if the diag type is set.
313
+ format.diag_border = 1 if format.diag_type != 0 && format.diag_border == 0
322
314
 
323
- if dxf_format
324
- write_sub_border('vertical')
325
- write_sub_border('horizontal')
326
- end
315
+ write_sub_border('diagonal', format.diag_border, format.diag_color)
327
316
  end
328
317
  end
329
318
 
319
+ def write_border_sub_elements(format)
320
+ write_sub_border('left', format.left, format.left_color)
321
+ write_sub_border('right', format.right, format.right_color)
322
+ write_sub_border('top', format.top, format.top_color)
323
+ write_sub_border('bottom', format.bottom, format.bottom_color)
324
+ end
325
+
326
+ BORDER_STYLES = %w(
327
+ none
328
+ thin
329
+ medium
330
+ dashed
331
+ dotted
332
+ thick
333
+ double
334
+ hair
335
+ mediumDashed
336
+ dashDot
337
+ mediumDashDot
338
+ dashDotDot
339
+ mediumDashDotDot
340
+ slantDashDot
341
+ )
342
+
330
343
  #
331
344
  # Write the <border> sub elements such as <right>, <top>, etc.
332
345
  #
@@ -336,24 +349,7 @@ def write_sub_border(type, style = 0, color = nil)
336
349
  return
337
350
  end
338
351
 
339
- border_styles = %w(
340
- none
341
- thin
342
- medium
343
- dashed
344
- dotted
345
- thick
346
- double
347
- hair
348
- mediumDashed
349
- dashDot
350
- mediumDashDot
351
- dashDotDot
352
- mediumDashDotDot
353
- slantDashDot
354
- )
355
-
356
- attributes = [ [:style, border_styles[style]] ]
352
+ attributes = [ [:style, BORDER_STYLES[style]] ]
357
353
 
358
354
  @writer.tag_elements(type, attributes) do
359
355
  if color != 0
@@ -401,16 +397,11 @@ def write_cell_xfs
401
397
  # Write the style <xf> element.
402
398
  #
403
399
  def write_style_xf
404
- num_fmt_id = 0
405
- font_id = 0
406
- fill_id = 0
407
- border_id = 0
408
-
409
400
  attributes = [
410
- ['numFmtId', num_fmt_id],
411
- ['fontId', font_id],
412
- ['fillId', fill_id],
413
- ['borderId', border_id]
401
+ ['numFmtId', 0],
402
+ ['fontId', 0],
403
+ ['fillId', 0],
404
+ ['borderId', 0]
414
405
  ]
415
406
 
416
407
  @writer.empty_tag('xf', attributes)
@@ -418,57 +409,40 @@ def write_style_xf
418
409
 
419
410
  private
420
411
 
412
+ def write_style_sheet_base
413
+ write_num_fmts
414
+ write_fonts
415
+ write_fills
416
+ write_borders
417
+ write_cell_style_xfs
418
+ write_cell_xfs
419
+ write_cell_styles
420
+ write_dxfs
421
+ write_table_styles
422
+ write_colors
423
+ end
424
+
421
425
  #
422
426
  # Write the <xf> element.
423
427
  #
424
428
  def write_xf(format)
425
- has_align = false
426
- has_protect = false
427
-
428
- attributes = [
429
- ['numFmtId', format.num_format_index],
430
- ['fontId' , format.font_index],
431
- ['fillId' , format.fill_index],
432
- ['borderId', format.border_index],
433
- ['xfId' , 0]
434
- ]
435
-
436
- attributes << ['applyNumberFormat', 1] if format.num_format_index > 0
437
-
438
- # Add applyFont attribute if XF format uses a font element.
439
- attributes << ['applyFont', 1] if format.font_index > 0
440
-
441
- # Add applyFill attribute if XF format uses a fill element.
442
- attributes << ['applyFill', 1] if format.fill_index > 0
443
-
444
- # Add applyBorder attribute if XF format uses a border element.
445
- attributes << ['applyBorder', 1] if format.border_index > 0
446
-
447
429
  # Check if XF format has alignment properties set.
448
430
  apply_align, align = format.get_align_properties
449
431
 
450
- # Check if an alignment sub-element should be written.
451
- has_align = true if apply_align && !align.empty?
452
-
453
- # We can also have applyAlignment without a sub-element.
454
- attributes << ['applyAlignment', 1] if apply_align
455
-
456
432
  # Check for cell protection properties.
457
433
  protection = format.get_protection_properties
458
434
 
459
- if protection
460
- attributes << ['applyProtection', 1]
461
- has_protect = true
462
- end
435
+ # Check if an alignment sub-element should be written.
436
+ has_align = apply_align && !align.empty?
463
437
 
464
438
  # Write XF with sub-elements if required.
465
- if has_align || has_protect
466
- @writer.tag_elements('xf', attributes) do
439
+ if has_align || protection
440
+ @writer.tag_elements('xf', format.xf_attributes) do
467
441
  @writer.empty_tag('alignment', align) if has_align
468
- @writer.empty_tag('protection', protection) if has_protect
442
+ @writer.empty_tag('protection', protection) if protection
469
443
  end
470
444
  else
471
- @writer.empty_tag('xf', attributes)
445
+ @writer.empty_tag('xf', format.xf_attributes)
472
446
  end
473
447
  end
474
448
 
@@ -488,14 +462,10 @@ def write_cell_styles
488
462
  # Write the <cellStyle> element.
489
463
  #
490
464
  def write_cell_style
491
- name = 'Normal'
492
- xf_id = 0
493
- builtin_id = 0
494
-
495
465
  attributes = [
496
- ['name', name],
497
- ['xfId', xf_id],
498
- ['builtinId', builtin_id]
466
+ ['name', 'Normal'],
467
+ ['xfId', 0],
468
+ ['builtinId', 0]
499
469
  ]
500
470
 
501
471
  @writer.empty_tag('cellStyle', attributes)
@@ -505,30 +475,30 @@ def write_cell_style
505
475
  # Write the <dxfs> element.
506
476
  #
507
477
  def write_dxfs
508
- formats = @dxf_formats
509
-
510
- count = formats.size
478
+ attributes = [ ['count', @dxf_formats.count] ]
511
479
 
512
- attributes = [ ['count', count] ]
513
-
514
- if !formats.empty?
480
+ if @dxf_formats.empty?
481
+ @writer.empty_tag('dxfs', attributes)
482
+ else
515
483
  @writer.tag_elements('dxfs', attributes) do
516
484
  # Write the font elements for format objects that have them.
517
485
  @dxf_formats.each do |format|
518
- @writer.tag_elements('dxf') do
519
- format.write_font(@writer, self, 1) if format.has_dxf_font?
486
+ write_dxf(format)
487
+ end
488
+ end
489
+ end
490
+ end
520
491
 
521
- if format.num_format_index != 0
522
- write_num_fmt(format.num_format_index, format.num_format)
523
- end
492
+ def write_dxf(format)
493
+ @writer.tag_elements('dxf') do
494
+ format.write_font(@writer, self, 1) if format.has_dxf_font?
524
495
 
525
- write_fill(format, 1) if format.has_dxf_fill?
526
- write_border(format, 1) if format.has_dxf_border?
527
- end
528
- end
496
+ if format.num_format_index != 0
497
+ write_num_fmt(format.num_format_index, format.num_format)
529
498
  end
530
- else
531
- @writer.empty_tag('dxfs', attributes)
499
+
500
+ write_fill(format, 1) if format.has_dxf_fill?
501
+ write_border(format, 1) if format.has_dxf_border?
532
502
  end
533
503
  end
534
504
 
@@ -536,14 +506,10 @@ def write_dxfs
536
506
  # Write the <tableStyles> element.
537
507
  #
538
508
  def write_table_styles
539
- count = 0
540
- default_table_style = 'TableStyleMedium9'
541
- default_pivot_style = 'PivotStyleLight16'
542
-
543
509
  attributes = [
544
- ['count', count],
545
- ['defaultTableStyle', default_table_style],
546
- ['defaultPivotStyle', default_pivot_style]
510
+ ['count', 0],
511
+ ['defaultTableStyle', 'TableStyleMedium9'],
512
+ ['defaultPivotStyle', 'PivotStyleLight16']
547
513
  ]
548
514
 
549
515
  @writer.empty_tag('tableStyles', attributes)
@@ -553,8 +519,6 @@ def write_table_styles
553
519
  # Write the <colors> element.
554
520
  #
555
521
  def write_colors
556
- custom_colors = @custom_colors
557
-
558
522
  return if @custom_colors.empty?
559
523
 
560
524
  @writer.tag_elements( 'colors' ) do
@@ -565,16 +529,15 @@ def write_colors
565
529
  #
566
530
  # Write the <mruColors> element for the most recently used colours.
567
531
  #
568
- def write_mru_colors(*args)
569
- custom_colors = args
570
-
532
+ def write_mru_colors(custom_colors)
571
533
  # Limit the mruColors to the last 10.
572
534
  count = custom_colors.size
535
+ # array[-10, 10] returns array which contains last 10 items.
573
536
  custom_colors = custom_colors[-10, 10] if count > 10
574
537
 
575
538
  @writer.tag_elements('mruColors') do
576
539
  # Write the custom colors in reverse order.
577
- @custom_colors.reverse.each do |color|
540
+ custom_colors.reverse.each do |color|
578
541
  write_color('rgb', color)
579
542
  end
580
543
  end
@@ -584,9 +547,7 @@ def write_mru_colors(*args)
584
547
  # Write the <condense> element.
585
548
  #
586
549
  def write_condense
587
- val = 0
588
-
589
- attributes = [ ['val', val] ]
550
+ attributes = [ ['val', 0] ]
590
551
 
591
552
  @writer.empty_tag('condense', attributes)
592
553
  end
@@ -595,9 +556,7 @@ def write_condense
595
556
  # Write the <extend> element.
596
557
  #
597
558
  def write_extend
598
- val = 0
599
-
600
- attributes = [ ['val', val] ]
559
+ attributes = [ ['val', 0] ]
601
560
 
602
561
  @writer.empty_tag('extend', attributes)
603
562
  end