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, delete_files, #float_to_str, #pixels_to_points, #ptrue?, #put_deprecate_message, #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, #write_anchor, #write_auto_fill, #write_comment_path, #write_div, #write_font, #write_stroke, #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
43
# File 'lib/write_xlsx/package/styles.rb', line 27

def assemble_xml_file
  write_xml_declaration
  write_style_sheet
  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
  @writer.end_tag('styleSheet')
  @writer.crlf
  @writer.close
end

#get_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.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/write_xlsx/package/styles.rb', line 63

def get_palette_color(index)
  palette = @palette

  # Handle colours in #XXXXXX RGB format.
  return "FF#{$1.upcase}" if index =~ /^#([0-9A-F]{6})$/i

  # Adjust the colour index.
  index -= 8

  # Palette is passed in from the Workbook class.
  rgb = @palette[index]

  sprintf("FF%02X%02X%02X", *rgb[0, 3])
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.



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

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.



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
329
330
331
332
333
334
335
336
# File 'lib/write_xlsx/package/styles.rb', line 302

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.



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

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.



379
380
381
382
383
384
385
386
# File 'lib/write_xlsx/package/styles.rb', line 379

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.



391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'lib/write_xlsx/package/styles.rb', line 391

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.



183
184
185
186
187
# File 'lib/write_xlsx/package/styles.rb', line 183

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.



212
213
214
215
216
# File 'lib/write_xlsx/package/styles.rb', line 212

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.



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
270
271
272
273
274
275
276
277
# File 'lib/write_xlsx/package/styles.rb', line 221

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 = get_palette_color(fg_color)
        @writer.empty_tag('fgColor', ['rgb', fg_color])
      end

      if bg_color && bg_color != 0
        bg_color = get_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.



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/write_xlsx/package/styles.rb', line 192

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.



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

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



290
291
292
293
294
295
296
297
# File 'lib/write_xlsx/package/styles.rb', line 290

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.



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
160
161
162
163
164
165
166
167
# File 'lib/write_xlsx/package/styles.rb', line 112

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.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/write_xlsx/package/styles.rb', line 92

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.



81
82
83
84
85
86
87
# File 'lib/write_xlsx/package/styles.rb', line 81

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

  attributes = ['xmlns', xmlns]

  @writer.start_tag('styleSheet', attributes)
end

#write_style_xfObject

Write the style <xf> element.



411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/write_xlsx/package/styles.rb', line 411

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.



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
367
368
369
370
371
372
373
374
# File 'lib/write_xlsx/package/styles.rb', line 341

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 = get_palette_color(color)
      @writer.empty_tag('color', ['rgb', color])
    else
      @writer.empty_tag('color', ['auto', 1])
    end
  end
end