Class: XlsxWriter::Cell

Inherits:
Object
  • Object
show all
Defined in:
lib/xlsx_writer/cell.rb

Constant Summary collapse

ABC =
('A'..'Z').to_a
MAX_DIGIT_WIDTH =
5
MAX_REASONABLE_WIDTH =
75
DATE_LENGTH =
'YYYY-MM-DD'.length
BOOLEAN_LENGTH =
'FALSE'.length + 1
JAN_1_1900 =
Time.parse('1899-12-30 00:00:00 UTC')
TRUE_FALSE_PATTERN =
%r{^true|false$}i
BIG_DECIMAL =
defined?(BigDecimal) ? BigDecimal : Struct.new
STYLE_NUMBER =
{
  :String     => 0,
  :Boolean    => 0,
  :Currency   => 1,
  :Date       => 2,
  :Integer    => 3,
  :Decimal    => 4,
}
TYPE_NAME =
{
  :String     => :s,
  :Boolean    => :b,
  :Currency   => :n,
  :Date       => :n,
  :Integer    => :n,
  :Decimal    => :n,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(row, raw_value, x, y) ⇒ Cell

Returns a new instance of Cell.



170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/xlsx_writer/cell.rb', line 170

def initialize(row, raw_value, x, y)
  @row = row
  @x = x
  @y = y
  if raw_value.is_a?(Hash)
    @value = raw_value[:value]
    @type = Cell.type @value, raw_value[:type]
    @faded_query = raw_value[:faded]
  else
    @value = raw_value
    @type = Cell.type value
  end
end

Instance Attribute Details

#rowObject (readonly)

Returns the value of attribute row.



164
165
166
# File 'lib/xlsx_writer/cell.rb', line 164

def row
  @row
end

#typeObject (readonly)

Returns the value of attribute type.



168
169
170
# File 'lib/xlsx_writer/cell.rb', line 168

def type
  @type
end

#valueObject (readonly)

Returns the value of attribute value.



167
168
169
# File 'lib/xlsx_writer/cell.rb', line 167

def value
  @value
end

#xObject (readonly)

Returns the value of attribute x.



165
166
167
# File 'lib/xlsx_writer/cell.rb', line 165

def x
  @x
end

#yObject (readonly)

Returns the value of attribute y.



166
167
168
# File 'lib/xlsx_writer/cell.rb', line 166

def y
  @y
end

Class Method Details

.character_width(value, type = nil) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/xlsx_writer/cell.rb', line 65

def character_width(value, type = nil)
  if type.nil?
    type = Cell.type(value)
  end
  case type
  when :String, :Integer
    value.to_s.length
  when :Decimal
    # -1000000.5
    round(value, 2).to_s.length + 2
  when :Currency
    # (1,000,000.50)
    len = round(value, 2).to_s.length + log_base(value.abs, 1e3).floor
    len += 2 if value < 0
    len
  when :Date
    DATE_LENGTH
  when :Boolean
    BOOLEAN_LENGTH
  else
    raise "Don't know character width for #{type.inspect}."
  end
end

.column_letter(i) ⇒ Object Also known as: excel_column_letter

0 -> A (zero based!)



7
8
9
10
11
12
13
14
15
# File 'lib/xlsx_writer/cell.rb', line 7

def column_letter(i)
  result = []
  while i >= 26 do
    result << ABC[i % 26]
    i /= 26
  end
  result << ABC[result.empty? ? i : i - 1]
  result.reverse.join
end

.escape(value, type = nil) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/xlsx_writer/cell.rb', line 89

def escape(value, type = nil)
  if type.nil?
    type = Cell.type(value)
  end
  case type
  when :Integer
    value.to_s
  when :Decimal, :Currency
    case value
    when BIG_DECIMAL
      value.to_s('F')
    when Rational
      value.to_f.to_s
    else
      value.to_s
    end
  when :Date
    # doesn't work for DateTimes or Times yet
    if value.is_a?(String)
      ((Time.parse(str) - JAN_1_1900) / 86_400).round
    elsif value.respond_to?(:to_date)
      (value.to_date - JAN_1_1900.to_date).to_i
    end
  when :Boolean
    value.to_s.downcase == 'true' ? 1 : 0
  else
    value.fast_xs
  end
end

.pixel_width(value, type = nil) ⇒ Object

width = Truncate([of Characters * Digit Width + pixel padding]/Digit Width*256)/256 Using the Calibri font as an example, the maximum digit width of 11 point font size is 7 pixels (at 96 dpi). In fact, each digit is the same width for this font. Therefore if the cell width is 8 characters wide, the value of this attribute shall be Truncate(/7*256)/256 = 8.7109375.



57
58
59
60
61
62
63
# File 'lib/xlsx_writer/cell.rb', line 57

def pixel_width(value, type = nil)
  if (w = ((character_width(value, type).to_f*MAX_DIGIT_WIDTH+5)/MAX_DIGIT_WIDTH*256)/256) < MAX_REASONABLE_WIDTH
    w
  else
    MAX_REASONABLE_WIDTH
  end
end

.style_number(type, faded = false) ⇒ Object



42
43
44
45
46
47
48
49
# File 'lib/xlsx_writer/cell.rb', line 42

def style_number(type, faded = false)
  style_number = STYLE_NUMBER[type] or raise("Don't know style number for #{type.inspect}. Must be #{STYLE_NUMBER.keys.map(&:inspect).join(', ')}.")
  if faded
    style_number * 2 + 1
  else
    style_number * 2
  end
end

.type(value, proposed = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/xlsx_writer/cell.rb', line 20

def type(value, proposed = nil)
  hint = if proposed
    proposed
  elsif value.is_a?(String) and value =~ TRUE_FALSE_PATTERN
    :Boolean
  else
    value.class.name.to_sym
  end
  case hint
  when :NilClass, :Symbol
    :String
  when :Fixnum
    :Integer
  when :Float, :Rational, :BigDecimal
    :Decimal
  when :TrueClass, :FalseClass
    :Boolean
  else
    hint
  end
end

.type_name(type) ⇒ Object



51
52
53
# File 'lib/xlsx_writer/cell.rb', line 51

def type_name(type)
  TYPE_NAME[type] or raise "Don't know type name for #{type.inspect}. Must be #{TYPE_NAME.keys.map(&:inspect).join(', ')}."
end

Instance Method Details

#empty?Boolean

Returns:

  • (Boolean)


188
189
190
191
# File 'lib/xlsx_writer/cell.rb', line 188

def empty?
  return @empty_query if defined?(@empty_query)
  @empty_query = (value.nil? or (value.is_a?(String) and value.empty?) or (value == false and row.sheet.document.quiet_booleans?))
end

#escaped_valueObject



205
206
207
208
209
210
211
212
213
# File 'lib/xlsx_writer/cell.rb', line 205

def escaped_value
  @escaped_value ||= begin
    if type == :String
      row.sheet.document.shared_strings.ndx value.to_s
    else
      Cell.escape value
    end
  end
end

#faded?Boolean

Returns:

  • (Boolean)


184
185
186
# File 'lib/xlsx_writer/cell.rb', line 184

def faded?
  @faded_query == true
end

#log_base(number, base) ⇒ Object



131
132
133
# File 'lib/xlsx_writer/cell.rb', line 131

def log_base(number, base)
  Math.log number, base
end

#pixel_widthObject



201
202
203
# File 'lib/xlsx_writer/cell.rb', line 201

def pixel_width
  @pixel_width ||= Cell.pixel_width value, type
end

#round(number, precision) ⇒ Object



120
121
122
# File 'lib/xlsx_writer/cell.rb', line 120

def round(number, precision)
  number.round precision
end

#to_xmlObject



193
194
195
196
197
198
199
# File 'lib/xlsx_writer/cell.rb', line 193

def to_xml
  if empty?
    %{<c r="#{Cell.column_letter(x)}#{y}" s="0" t="s" />}
  else
    %{<c r="#{Cell.column_letter(x)}#{y}" s="#{Cell.style_number(type, faded?)}" t="#{Cell.type_name(type)}"><v>#{escaped_value}</v></c>}
  end
end