Class: Writexlsx::Package::Styles

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

Constant Summary collapse

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 => '@'
}
PATTERNS =
%w(
  none
  solid
  mediumGray
  darkGray
  lightGray
  darkHorizontal
  darkVertical
  darkDown
  darkUp
  darkGrid
  darkTrellis
  lightHorizontal
  lightVertical
  lightDown
  lightUp
  lightGrid
  lightTrellis
  gray125
  gray0625
)
BORDER_STYLES =
%w(
  none
  thin
  medium
  dashed
  dotted
  thick
  double
  hair
  mediumDashed
  dashDot
  mediumDashDot
  dashDotDot
  mediumDashDotDot
  slantDashDot
)

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, #process_workbook_options, #ptrue?, #put_deprecate_message, #quote_sheetname, #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
# File 'lib/write_xlsx/package/styles.rb', line 27

def assemble_xml_file
  write_xml_declaration do
    write_style_sheet { write_style_sheet_base }
  end
end

#bg_and_fg_color(format, dxf_format) ⇒ Object


255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/write_xlsx/package/styles.rb', line 255

def bg_and_fg_color(format, dxf_format)
  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

  [bg_color, fg_color]
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.


51
52
53
54
55
56
57
# File 'lib/write_xlsx/package/styles.rb', line 51

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.


36
37
38
39
40
41
42
43
44
45
# File 'lib/write_xlsx/package/styles.rb', line 36

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.


296
297
298
299
300
301
# File 'lib/write_xlsx/package/styles.rb', line 296

def write_border(format, dxf_format = nil)
  # Write the start border tag.
  @writer.tag_elements('border', format.border_attributes) do
    write_border_base(format, dxf_format)
  end
end

#write_border_base(format, dxf_format) ⇒ Object


303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/write_xlsx/package/styles.rb', line 303

def write_border_base(format, dxf_format)
  # Write the <border> sub elements.
  write_border_sub_elements(format)

  # Condition DXF formats don't allow diagonal borders
  if dxf_format
    write_sub_border('vertical')
    write_sub_border('horizontal')
  else
    # 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_sub_border('diagonal', format.diag_border, format.diag_color)
  end
end

#write_border_sub_elements(format) ⇒ Object


319
320
321
322
323
324
# File 'lib/write_xlsx/package/styles.rb', line 319

def write_border_sub_elements(format)
  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)
end

#write_bordersObject

Write the <borders> element.


272
273
274
275
276
# File 'lib/write_xlsx/package/styles.rb', line 272

def write_borders
  write_format_elements('borders', @border_count) do
    write_borders_base
  end
end

#write_borders_baseObject


278
279
280
281
282
# File 'lib/write_xlsx/package/styles.rb', line 278

def write_borders_base
  @xf_formats.each do |format|
    write_border(format) if format.has_border?
  end
end

#write_cell_style_xfsObject

Write the <cellStyleXfs> element.


367
368
369
370
371
372
373
374
# File 'lib/write_xlsx/package/styles.rb', line 367

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.


379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/write_xlsx/package/styles.rb', line 379

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.


160
161
162
163
164
# File 'lib/write_xlsx/package/styles.rb', line 160

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.


191
192
193
194
195
# File 'lib/write_xlsx/package/styles.rb', line 191

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.


222
223
224
225
226
# File 'lib/write_xlsx/package/styles.rb', line 222

def write_fill(format, dxf_format = nil)
  @writer.tag_elements('fill' ) do
    write_fill_base(format, dxf_format)
  end
end

#write_fill_base(format, dxf_format) ⇒ Object


228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/write_xlsx/package/styles.rb', line 228

def write_fill_base(format, dxf_format)
  # 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
    write_pattern_fill(format, dxf_format)
  end
end

#write_fillsObject

Write the <fills> element.


169
170
171
172
173
174
175
# File 'lib/write_xlsx/package/styles.rb', line 169

def write_fills
  attributes = [ ['count', @fill_count] ]

  @writer.tag_elements('fills', attributes) do
    write_fills_base
  end
end

#write_fills_baseObject


177
178
179
180
181
182
183
184
185
186
# File 'lib/write_xlsx/package/styles.rb', line 177

def write_fills_base
  # 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

#write_font_baseObject


151
152
153
154
155
# File 'lib/write_xlsx/package/styles.rb', line 151

def write_font_base
  @xf_formats.each do |format|
    format.write_font(@writer, self) if format.has_font?
  end
end

#write_fontsObject

Write the <fonts> element.


145
146
147
148
149
# File 'lib/write_xlsx/package/styles.rb', line 145

def write_fonts
  write_format_elements('fonts', @font_count) do
    write_font_base
  end
end

#write_format_elements(elements, count) ⇒ Object


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

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.


130
131
132
133
134
135
136
137
138
139
140
# File 'lib/write_xlsx/package/styles.rb', line 130

def write_num_fmt(num_fmt_id, format_code)
  # Set the format code for built-in number formats.
  format_code = FORMAT_CODES[num_fmt_id] || 'General' if num_fmt_id < 164

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

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

#write_num_fmtsObject

Write the <numFmts> element.


71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/write_xlsx/package/styles.rb', line 71

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_pattern_fill(format, dxf_format) ⇒ Object


241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/write_xlsx/package/styles.rb', line 241

def write_pattern_fill(format, dxf_format)
  bg_color, fg_color = bg_and_fg_color(format, dxf_format)

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

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

#write_style_sheetObject

Write the <styleSheet> element.


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

def write_style_sheet
  attributes = [ ['xmlns', XMLWriterSimple::XMLNS] ]

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

#write_style_xfObject

Write the style <xf> element.


399
400
401
402
403
404
405
406
407
408
# File 'lib/write_xlsx/package/styles.rb', line 399

def write_style_xf
  attributes = [
    ['numFmtId', 0],
    ['fontId',   0],
    ['fillId',   0],
    ['borderId', 0]
  ]

  @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.


346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/write_xlsx/package/styles.rb', line 346

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

  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