class Format COLORS = { 'aqua' => 0x0F, 'black' => 0x08, 'blue' => 0x0C, 'brown' => 0x10, 'cyan' => 0x0F, 'fuchsia' => 0x0E, 'gray' => 0x17, 'grey' => 0x17, 'green' => 0x11, 'lime' => 0x0B, 'magenta' => 0x0E, 'navy' => 0x12, 'orange' => 0x1D, 'purple' => 0x24, 'red' => 0x0A, 'silver' => 0x16, 'white' => 0x09, 'yellow' => 0x0D } attr_accessor :xf_index def initialize(args={}, xf_index=0) defaults = {} defaults.update(:color => 0x7FFF, :bold => 0x0190) defaults.update(:fg_color => 0x40, :pattern => 0, :size => 10) defaults.update(:bg_color => 0x41, :rotation => 0, :font => "Arial") defaults.update(:underline => 0, :italic => 0, :top => 0) defaults.update(:bottom => 0, :right => 0, :left => 0) defaults.update(:font_index => 0, :font_family => 0) defaults.update(:font_strikeout => 0, :font_script => 0) defaults.update(:font_outline => 0, :left_color => 0) defaults.update(:font_charset => 0, :right_color => 0) defaults.update(:font_shadow => 0, :top_color => 0x40) defaults.update(:text_v_align => 2, :bottom_color => 0x40) defaults.update(:text_h_align => 0, :num_format => 0) defaults.update(:text_justlast => 0, :text_wrap => 0) ######################################################################## # We must manually create accessors for these so that they can handle # both 0/1 and true/false. ######################################################################## no_acc = [:bold,:italic,:underline,:strikeout,:text_wrap,:text_justlast] no_acc.push(:fg_color,:bg_color,:color,:font_outline,:font_shadow) args.each{|key,val| key = key.to_s.downcase.intern val = 1 if val == true val = 0 if val == false defaults.fetch(key) defaults.update(key=>val) } defaults.each{|key,val| unless no_acc.member?(key) self.class.send(:attr_accessor,"#{key}") end send("#{key}=",val) } @xf_index = xf_index yield self if block_given? end def color=(colour) if COLORS.has_key?(colour) @color = COLORS[colour] else if colour.kind_of?(String) raise ArgumentError, "unknown color" else @color = colour end end @color end def bg_color=(colour) if COLORS.has_key?(colour) @bg_color = COLORS[colour] else if colour.kind_of?(String) raise ArgumentError, "unknown color" else @bg_color = colour end end @bg_color end def fg_color=(colour) if COLORS.has_key?(colour) @fg_color = COLORS[colour] else if colour.kind_of?(String) raise ArgumentError, "unknown color" else @fg_color = colour end end @fg_color end def fg_color @fg_color end def bg_color @bg_color end # Should I return the stringified version of the color if applicable? def color #COLORS.invert.fetch(@color) @color end def italic return true if @italic >= 1 return false end def italic=(val) val = 1 if val == true val = 0 if val == false @italic = val end def font_shadow return true if @font_shadow == 1 return false end def font_shadow=(val) val = 1 if val == true val = 0 if val == false @font_shadow = val end def font_outline return true if @font_outline == 1 return false end def font_outline=(val) val = 1 if val == true val = 0 if val == false @font_outline = val end def text_justlast return true if @text_justlast == 1 return false end def text_justlast=(val) val = 1 if val == true val = 0 if val == false @text_justlast = val end def text_wrap return true if @text_wrap == 1 return false end def text_wrap=(val) val = 1 if val == true val = 0 if val == false @text_wrap = val end def strikeout return true if @strikeout == 1 return false end def strikeout=(val) val = 1 if val == true val = 0 if val == false @strikeout = val end def underline return true if @underline == 1 return false end def underline=(val) val = 1 if val == true val = 0 if val == false @underline = val end def xf_biff(style=0) atr_num = 0 atr_num = 1 if @num_format != 0 atr_fnt = 0 atr_fnt = 1 if @font_index != 0 atr_alc = @text_wrap atr_bdr = [@bottom,@top,@left,@right].find{ |n| n > 0 } || 0 atr_pat = [@fg_color,@bg_color,@pattern].find{ |n| n > 0 } || 0 atr_prot = 0 @bottom_color = 0 if @bottom == 0 @top_color = 0 if @top == 0 @right_color = 0 if @right == 0 @left_color = 0 if @left == 0 record = 0x00E0 length = 0x0010 align = @text_h_align align |= @text_wrap << 3 align |= @text_v_align << 4 align |= @text_justlast << 7 align |= @rotation << 8 align |= atr_num << 10 align |= atr_fnt << 11 align |= atr_alc << 12 align |= atr_bdr << 13 align |= atr_pat << 14 align |= atr_prot << 15 # Assume a solid fill color if the bg_color or fg_color are set but # the pattern value is not set if @pattern <= 0x01 and @bg_color != 0x41 and @fg_color == 0x40 @fg_color = @bg_color @bg_color = 0x40 @pattern = 1 end if @pattern < 0x01 and @bg_color == 0x41 and @fg_color != 0x40 @bg_color = 0x40 @pattern = 1 end icv = @fg_color icv |= @bg_color << 7 fill = @pattern fill |= @bottom << 6 fill |= @bottom_color << 9 border1 = @top border1 |= @left << 3 border1 |= @right << 6 border1 |= @top_color << 9 border2 = @left_color border2 |= @right_color << 7 header = [record,length].pack("vv") fields = [@font_index,@num_format,style,align,icv,fill,border1,border2] data = fields.pack("vvvvvvvv") rv = header + data return rv end def font_biff dyheight = @size * 20 cch = @font.length record = 0x31 length = 0x0F + cch reserved = 0x00 grbit = 0x00 grbit |= 0x02 if @italic > 0 grbit |= 0x08 if @font_strikeout > 0 grbit |= 0x10 if @font_outline > 0 grbit |= 0x20 if @font_shadow > 0 header = [record,length].pack("vv") fields = [dyheight,grbit,@color,@bold,@font_script,@underline,@font_family] fields.push(@font_charset,reserved,cch) data = fields.pack("vvvvvCCCCC") rv = header + data + @font return rv end def font_key key = @font.to_s + @size.to_s + @font_script.to_s + @underline.to_s key += @font_strikeout.to_s + @bold.to_s + @font_outline.to_s key += @font_family.to_s + @font_charset.to_s + @font_shadow.to_s key += @color.to_s + @italic.to_s return key end def align=(location = nil) return if location.nil? return if location.kind_of?(Fixnum) location.downcase! @text_h_align = 1 if location == 'left' @text_h_align = 2 if location == 'centre' @text_h_align = 2 if location == 'center' @text_h_align = 3 if location == 'right' @text_h_align = 4 if location == 'fill' @text_h_align = 5 if location == 'justify' @text_h_align = 6 if location == 'merge' @text_v_align = 0 if location == 'top' @text_v_align = 1 if location == 'vcentre' @text_v_align = 1 if location == 'vcenter' @text_v_align = 2 if location == 'bottom' @text_v_align = 3 if location == 'vjustify' end def align [@text_h_align,@text_v_align] end def bold=(weight) weight = 1 if weight == true weight = 0 if weight == false weight = 0x2BC if weight.nil? weight = 0x2BC if weight == 1 weight = 0x190 if weight == 0 weight = 0x190 if weight < 0x064 weight = 0x190 if weight > 0x3E8 @bold = weight @bold end def bold return true if @bold >= 1 return false end def border=(style) [@bottom,@top,@right,@left].each{ |attr| attr = style } end def border [@bottom,@top,@right,@left] end def border_color=(color) [@bottom_color,@top_color,@left_color,@right_color].each{ |a| a = color } end def border_color [@bottom_color,@top_color,@left_color,@right_color] end end