write_xlsx 0.81.1 → 0.83.0

Sign up to get free protection for your applications and to get access to all the features.
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