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 '1900-01-01'
TRUE_FALSE_PATTERN =
%r{^true|false$}i

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(row, data) ⇒ Cell

Returns a new instance of Cell.



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

def initialize(row, data)
  @row = row
  if data.is_a?(::Hash)
    data = data.symbolize_keys
    @value = data[:value]
    faded = data[:faded]
    calculated_type = data[:type] || Cell.calculate_type(@value)
  else
    @value = data
    faded = false
    calculated_type = Cell.calculate_type @value
  end
  character_width = Cell.character_width @value, calculated_type
  @pixel_width = Cell.pixel_width character_width
  @excel_type = Cell.excel_type calculated_type
  @excel_style_number = Cell.excel_style_number calculated_type, faded
  @excel_value = Cell.send "excel_#{calculated_type.to_s.underscore}", @value
end

Instance Attribute Details

#excel_style_numberObject (readonly)

Returns the value of attribute excel_style_number.



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

def excel_style_number
  @excel_style_number
end

#excel_typeObject (readonly)

Returns the value of attribute excel_type.



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

def excel_type
  @excel_type
end

#excel_valueObject (readonly)

Returns the value of attribute excel_value.



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

def excel_value
  @excel_value
end

#pixel_widthObject (readonly)

Returns the value of attribute pixel_width.



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

def pixel_width
  @pixel_width
end

#rowObject (readonly)

Returns the value of attribute row.



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

def row
  @row
end

#valueObject (readonly)

Returns the value of attribute value.



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

def value
  @value
end

Class Method Details

.calculate_type(value) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/xlsx_writer/cell.rb', line 93

def calculate_type(value)
  case value
  when Date
    :Date
  when Integer
    :Integer
  when Float
    :Decimal
  when Numeric
    :Number
  when TrueClass, FalseClass, TRUE_FALSE_PATTERN
    :Boolean
  else
    if (defined?(Decimal) and value.is_a?(Decimal)) or (defined?(BigDecimal) and value.is_a?(BigDecimal))
      :Decimal
    else
      :String
    end
  end
end

.character_width(value, calculated_type = nil) ⇒ Object



114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/xlsx_writer/cell.rb', line 114

def character_width(value, calculated_type = nil)
  calculated_type ||= calculate_type(value)
  case calculated_type
  when :String
    value.to_s.length
  when :Number, :Integer, :Decimal
    # -1000000.5
    len = round(value, 2).to_s.length
    len += 2 if calculated_type == :Decimal
    len += 1 if value < 0
    len
  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
  end
end

.excel_boolean(value) ⇒ Object



80
81
82
# File 'lib/xlsx_writer/cell.rb', line 80

def excel_boolean(value)
  value ? 1 : 0
end

.excel_column_letter(i) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/xlsx_writer/cell.rb', line 45

def excel_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

.excel_date(value) ⇒ Object

doesn’t necessarily work for times yet



72
73
74
75
76
77
78
# File 'lib/xlsx_writer/cell.rb', line 72

def excel_date(value)
  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
end

.excel_number(value) ⇒ Object Also known as: excel_currency, excel_integer, excel_decimal



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

def excel_number(value)
  str = value.to_s.dup
  unless str =~ /\A[0-9\.\-]*\z/
    raise ::ArgumentError, %{Bad value "#{value}" Only numbers and dots (.) allowed in number fields}
  end
  str.fast_xs
end

.excel_string(value) ⇒ Object



55
56
57
# File 'lib/xlsx_writer/cell.rb', line 55

def excel_string(value)
  value.to_s.fast_xs
end

.excel_style_number(calculated_type, faded = false) ⇒ Object

TODO make a class for this



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

def excel_style_number(calculated_type, faded = false)
  i = case calculated_type
  when :String
    0
  when :Boolean
    0 # todo
  when :Currency
    1
  when :Date
    2
  when :Number, :Integer
    3
  when :Decimal
    4
  else
    raise ::ArgumentError, "Unknown cell type #{k}"
  end
  if faded
    i * 2 + 1
  else
    i * 2
  end
end

.excel_type(calculated_type) ⇒ Object

TODO make a class for this



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

def excel_type(calculated_type)
  case calculated_type
  when :String
    :inlineStr
  when :Number, :Integer, :Decimal, :Date, :Currency
    :n
  when :Boolean
    :b
  else
    raise ::ArgumentError, "Unknown cell type #{calculated_type}"
  end
end

.pixel_width(character_width) ⇒ 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.



86
87
88
89
90
91
# File 'lib/xlsx_writer/cell.rb', line 86

def pixel_width(character_width)
  [
    ((character_width.to_f*MAX_DIGIT_WIDTH+5)/MAX_DIGIT_WIDTH*256)/256,
    MAX_REASONABLE_WIDTH
  ].min
end

Instance Method Details

#excel_column_letterObject

0 -> A (zero based!)



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

def excel_column_letter
  Cell.excel_column_letter row.cells.index(self)
end

#log_base(number, base) ⇒ Object



149
150
151
# File 'lib/xlsx_writer/cell.rb', line 149

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

#round(number, precision) ⇒ Object



138
139
140
# File 'lib/xlsx_writer/cell.rb', line 138

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

#to_xmlObject



189
190
191
192
193
194
195
196
197
# File 'lib/xlsx_writer/cell.rb', line 189

def to_xml
  if value.nil? or (value.is_a?(String) and value.empty?)
    %{<c r="#{excel_column_letter}#{row.ndx}" s="0" t="inlineStr" />}
  elsif excel_type == :inlineStr
    %{<c r="#{excel_column_letter}#{row.ndx}" s="#{excel_style_number}" t="#{excel_type}"><is><t>#{excel_value}</t></is></c>}
  else
    %{<c r="#{excel_column_letter}#{row.ndx}" s="#{excel_style_number}" t="#{excel_type}"><v>#{excel_value}</v></c>}
  end
end