Class: Writexlsx::Package::Styles

Inherits:
Object
  • Object
show all
Includes:
Utility
Defined in:
lib/write_xlsx/package/styles.rb

Constant Summary

Constants included from Utility

Utility::COL_MAX, Utility::ROW_MAX, Utility::SHEETNAME_MAX, Utility::STR_MAX

Instance Method Summary collapse

Methods included from Utility

#absolute_char, #check_dimensions, #check_dimensions_and_update_max_min_values, #check_parameter, #convert_date_time, #dash_types, delete_files, #fill_properties, #float_to_str, #layout_properties, #line_fill_properties, #line_properties, #pixels_to_points, #ptrue?, #put_deprecate_message, #r_id_attributes, #row_col_notation, #shape_style_base, #store_col_max_min_values, #store_row_max_min_values, #substitute_cellref, #underline_attributes, #v_shape_attributes_base, #v_shape_style_base, #value_or_raise, #write_anchor, #write_auto_fill, #write_comment_path, #write_div, #write_font, #write_stroke, #write_xml_declaration, #xl_cell_to_rowcol, #xl_col_to_name, #xl_range, #xl_range_formula, #xl_rowcol_to_cell, #xml_str

Constructor Details

#initializeStyles



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/write_xlsx/package/styles.rb', line 11

def initialize
  @writer = Package::XMLWriterSimple.new
  @xf_formats       = nil
  @palette          = []
  @font_count       = 0
  @num_format_count = 0
  @border_count     = 0
  @fill_count       = 0
  @custom_colors    = []
  @dxf_formats      = []
end

Instance Method Details

#assemble_xml_fileObject



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/write_xlsx/package/styles.rb', line 27

def assemble_xml_file
  write_xml_declaration do
    write_style_sheet do
      write_num_fmts
      write_fonts
      write_fills
      write_borders
      write_cell_style_xfs
      write_cell_xfs
      write_cell_styles
      write_dxfs
      write_table_styles
      write_colors
    end
  end
end

#palette_color(index) ⇒ Object

Convert from an Excel internal colour index to a XML style #RRGGBB index based on the default or user defined values in the Workbook palette.



62
63
64
65
66
67
68
# File 'lib/write_xlsx/package/styles.rb', line 62

def palette_color(index)
if index =~ /^#([0-9A-F]{6})$/i
  "FF#{$1.upcase}"
else
  "FF#{super(index)}"
end
end

#set_style_properties(xf_formats, palette, font_count, num_format_count, border_count, fill_count, custom_colors, dxf_formats) ⇒ Object

Pass in the Format objects and other properties used to set the styles.



47
48
49
50
51
52
53
54
55
56
# File 'lib/write_xlsx/package/styles.rb', line 47

def set_style_properties(xf_formats, palette, font_count, num_format_count, border_count, fill_count, custom_colors, dxf_formats)
  @xf_formats       = xf_formats
  @palette          = palette
  @font_count       = font_count
  @num_format_count = num_format_count
  @border_count     = border_count
  @fill_count       = fill_count
  @custom_colors    = custom_colors
  @dxf_formats      = dxf_formats
end

#set_xml_writer(filename) ⇒ Object



23
24
25
# File 'lib/write_xlsx/package/styles.rb', line 23

def set_xml_writer(filename)
  @writer.set_xml_writer(filename)
end

#write_border(format, dxf_format = nil) ⇒ Object

Write the <border> element.



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/write_xlsx/package/styles.rb', line 294

def write_border(format, dxf_format = nil)
  attributes = []

  # Diagonal borders add attributes to the <border> element.
  if format.diag_type == 1
    attributes << ['diagonalUp',   1]
  elsif format.diag_type == 2
    attributes << ['diagonalDown', 1]
  elsif format.diag_type == 3
    attributes << ['diagonalUp',   1]
    attributes << ['diagonalDown', 1]
  end

  # Ensure that a default diag border is set if the diag type is set.
  format.diag_border = 1 if format.diag_type != 0 && format.diag_border == 0

  # Write the start border tag.
  @writer.tag_elements('border', attributes) do
    # Write the <border> sub elements.
    write_sub_border('left',   format.left,   format.left_color)
    write_sub_border('right',  format.right,  format.right_color)
    write_sub_border('top',    format.top,    format.top_color)
    write_sub_border('bottom', format.bottom, format.bottom_color)

    # Condition DXF formats don't allow diagonal borders
    if !dxf_format
      write_sub_border('diagonal', format.diag_border, format.diag_color)
    end

    if dxf_format
      write_sub_border('vertical')
      write_sub_border('horizontal')
    end
  end
end

#write_bordersObject

Write the <borders> element.



274
275
276
277
278
279
280
# File 'lib/write_xlsx/package/styles.rb', line 274

def write_borders
  write_format_elements('borders', @border_count) do
    @xf_formats.each do |format|
      write_border(format) if format.has_border?
    end
  end
end

#write_cell_style_xfsObject

Write the <cellStyleXfs> element.



371
372
373
374
375
376
377
378
# File 'lib/write_xlsx/package/styles.rb', line 371

def write_cell_style_xfs
  attributes = [ ['count', 1] ]

  @writer.tag_elements('cellStyleXfs', attributes) do
    # Write the style_xf element.
    write_style_xf
  end
end

#write_cell_xfsObject

Write the <cellXfs> element.



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/write_xlsx/package/styles.rb', line 383

def write_cell_xfs
  formats = @xf_formats

  # Workaround for when the last format is used for the comment font
  # and shouldn't be used for cellXfs.
  last_format =   formats[-1]

  formats.pop if last_format && last_format.font_only != 0

  attributes = [ ['count', formats.size] ]

  @writer.tag_elements('cellXfs', attributes) do
    # Write the xf elements.
    formats.each { |format| write_xf(format) }
  end
end

#write_color(name, value) ⇒ Object

Write the <color> element.



175
176
177
178
179
# File 'lib/write_xlsx/package/styles.rb', line 175

def write_color(name, value)
  attributes = [ [name, value] ]

  @writer.empty_tag('color', attributes)
end

#write_default_fill(pattern_type) ⇒ Object

Write the <fill> element for the default fills.



204
205
206
207
208
# File 'lib/write_xlsx/package/styles.rb', line 204

def write_default_fill(pattern_type)
  @writer.tag_elements('fill') do
    @writer.empty_tag('patternFill', [ ['patternType', pattern_type] ])
  end
end

#write_fill(format, dxf_format = nil) ⇒ Object

Write the <fill> element.



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/write_xlsx/package/styles.rb', line 213

def write_fill(format, dxf_format = nil)
  pattern    = format.pattern
  bg_color   = format.bg_color
  fg_color   = format.fg_color

  # Colors for dxf formats are handled differently from normal formats since
  # the normal format reverses the meaning of BG and FG for solid fills.
  if dxf_format && dxf_format != 0
    bg_color = format.dxf_bg_color
    fg_color = format.dxf_fg_color
  end

  patterns = %w(
    none
    solid
    mediumGray
    darkGray
    lightGray
    darkHorizontal
    darkVertical
    darkDown
    darkUp
    darkGrid
    darkTrellis
    lightHorizontal
    lightVertical
    lightDown
    lightUp
    lightGrid
    lightTrellis
    gray125
    gray0625
  )

  @writer.tag_elements('fill' ) do
    # The "none" pattern is handled differently for dxf formats.
    if dxf_format && format.pattern <= 1
      attributes = []
    else
      attributes = [ ['patternType', patterns[format.pattern]] ]
    end

    @writer.tag_elements('patternFill', attributes) do
      if fg_color && fg_color != 0
        fg_color = palette_color(fg_color)
        @writer.empty_tag('fgColor', [ ['rgb', fg_color] ])
      end

      if bg_color && bg_color != 0
        bg_color = palette_color(bg_color)
        @writer.empty_tag('bgColor', [ ['rgb', bg_color] ])
      else
        @writer.empty_tag('bgColor', [ ['indexed', 64] ]) if !dxf_format
      end
    end
  end
end

#write_fillsObject

Write the <fills> element.



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/write_xlsx/package/styles.rb', line 184

def write_fills
  count = @fill_count

  attributes = [ ['count', count] ]

  @writer.tag_elements('fills', attributes) do
    # Write the default fill element.
    write_default_fill('none')
    write_default_fill('gray125')

    # Write the fill elements for format objects that have them.
    @xf_formats.each do |format|
      write_fill(format) if format.has_fill?
    end
  end
end

#write_fontsObject

Write the <fonts> element.



164
165
166
167
168
169
170
# File 'lib/write_xlsx/package/styles.rb', line 164

def write_fonts
  write_format_elements('fonts', @font_count) do
    @xf_formats.each do |format|
      format.write_font(@writer, self) if format.has_font?
    end
  end
end

#write_format_elements(elements, count) ⇒ Object



282
283
284
285
286
287
288
289
# File 'lib/write_xlsx/package/styles.rb', line 282

def write_format_elements(elements, count)
  attributes = [ [ 'count', count] ]

  @writer.tag_elements(elements, attributes) do
    # Write the border elements for format objects that have them.
    yield
  end
end

#write_num_fmt(num_fmt_id, format_code) ⇒ Object

Write the <numFmt> element.



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/write_xlsx/package/styles.rb', line 104

def write_num_fmt(num_fmt_id, format_code)
  format_codes = {
    0  => 'General',
    1  => '0',
    2  => '0.00',
    3  => '#,##0',
    4  => '#,##0.00',
    5  => '($#,##0_);($#,##0)',
    6  => '($#,##0_);[Red]($#,##0)',
    7  => '($#,##0.00_);($#,##0.00)',
    8  => '($#,##0.00_);[Red]($#,##0.00)',
    9  => '0%',
    10 => '0.00%',
    11 => '0.00E+00',
    12 => '# ?/?',
    13 => '# ??/??',
    14 => 'm/d/yy',
    15 => 'd-mmm-yy',
    16 => 'd-mmm',
    17 => 'mmm-yy',
    18 => 'h:mm AM/PM',
    19 => 'h:mm:ss AM/PM',
    20 => 'h:mm',
    21 => 'h:mm:ss',
    22 => 'm/d/yy h:mm',
    37 => '(#,##0_);(#,##0)',
    38 => '(#,##0_);[Red](#,##0)',
    39 => '(#,##0.00_);(#,##0.00)',
    40 => '(#,##0.00_);[Red](#,##0.00)',
    41 => '_(* #,##0_);_(* (#,##0);_(* "-"_);_(@_)',
    42 => '_($* #,##0_);_($* (#,##0);_($* "-"_);_(@_)',
    43 => '_(* #,##0.00_);_(* (#,##0.00);_(* "-"??_);_(@_)',
    44 => '_($* #,##0.00_);_($* (#,##0.00);_($* "-"??_);_(@_)',
    45 => 'mm:ss',
    46 => '[h]:mm:ss',
    47 => 'mm:ss.0',
    48 => '##0.0E+0',
    49 => '@'
  }

  # Set the format code for built-in number formats.
  if num_fmt_id < 164
    if format_codes[num_fmt_id]
      format_code = format_codes[num_fmt_id]
    else
      format_code = 'General'
    end
  end

  attributes = [
    ['numFmtId',   num_fmt_id],
    ['formatCode', format_code]
  ]

  @writer.empty_tag('numFmt', attributes)
end

#write_num_fmtsObject

Write the <numFmts> element.



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/write_xlsx/package/styles.rb', line 84

def write_num_fmts
  count = @num_format_count

  return if count == 0

  attributes = [ ['count', count] ]

  @writer.tag_elements('numFmts', attributes) do
    # Write the numFmts elements.
    @xf_formats.each do |format|
      # Ignore built-in number formats, i.e., < 164.
      next unless format.num_format_index >= 164
      write_num_fmt(format.num_format_index, format.num_format)
    end
  end
end

#write_style_sheetObject

Write the <styleSheet> element.



73
74
75
76
77
78
79
# File 'lib/write_xlsx/package/styles.rb', line 73

def write_style_sheet
  xmlns = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main'

  attributes = [ ['xmlns', xmlns] ]

  @writer.tag_elements('styleSheet', attributes) { yield }
end

#write_style_xfObject

Write the style <xf> element.



403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/write_xlsx/package/styles.rb', line 403

def write_style_xf
  num_fmt_id = 0
  font_id    = 0
  fill_id    = 0
  border_id  = 0

  attributes = [
    ['numFmtId', num_fmt_id],
    ['fontId',   font_id],
    ['fillId',   fill_id],
    ['borderId', border_id]
  ]

  @writer.empty_tag('xf', attributes)
end

#write_sub_border(type, style = 0, color = nil) ⇒ Object

Write the <border> sub elements such as <right>, <top>, etc.



333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/write_xlsx/package/styles.rb', line 333

def write_sub_border(type, style = 0, color = nil)
  if style == 0
    @writer.empty_tag(type)
    return
  end

  border_styles = %w(
    none
    thin
    medium
    dashed
    dotted
    thick
    double
    hair
    mediumDashed
    dashDot
    mediumDashDot
    dashDotDot
    mediumDashDotDot
    slantDashDot
  )

  attributes = [ [:style, border_styles[style]] ]

  @writer.tag_elements(type, attributes) do
    if color != 0
      color = palette_color(color)
      @writer.empty_tag('color', [ ['rgb', color] ])
    else
      @writer.empty_tag('color', [ ['auto', 1] ])
    end
  end
end