###################################################################### # Spreadsheet Alpha 2 # # Changelog # ========= # - Excel is now a subclass of File # - Method write() was changed to write_data() to avoid IO confusion # - Type checking in write_data() now done with kind_of? method instead # - Uses big_endian? boolean instead of @byte_order value ###################################################################### module Spreadsheet class OutOfRangeException < RuntimeError; end class InvalidTypeException < RuntimeError; end class Excel < File RowMax = 65536 ColMax = 256 StrMax = 255 def initialize(filename) super(filename,"w+") @dim_offset = 0 @big_endian? = false # Big Endian or Little Endian architecture? if [1].pack("I") == [1].pack("N") @big_endian? = true end write_bof() write_dimensions() end def write_bof name = 0x0809 # Record identifier len = 0x0008 # Number of bytes version = 0x0000 type = 0x0010 # Worksheet build = 0x0000 # Set to zero year = 0x0000 # Set to zero header = [name,len].pack("vv") data = [version,type,build,year].pack("vvvv") hd = header + data print(hd) end def write_dimensions(row_min=0,row_max=0,col_min=0,col_max=0) row_max += 1 col_max += 1 name = 0x0000 len = 0x000A res = 0x0000 header = [name,len].pack("vv") data = [row_min,row_max,col_min,col_max,res].pack("vvvvv") hd = header + data @dim_offset = tell print(hd) end def write_eof name = 0x000A len = 0x0000 header = [name,len].pack("vv") print(header) seek(@dim_offset,0) write_dimensions() end def close write_eof() super end def write_data(row=0,col=0,data=nil) if data.kind_of?(String) write_string(row,col,data) elsif data.kind_of(Fixnum) write_number(row,col,data) else raise InvalidTypeException end end def write_string(row,col,string) raise OutOfRangeException if row > RowMax raise OutOfRangeException if col > ColMax name = 0x0204 # Record identifier xf = 0x0000 # Cell format strlen = string.length string.slice!(0,StrMax) if strlen > StrMax len = 0x0008 + strlen # Bytes to follow header = [name,len].pack("vv") data = [row,col,xf,strlen].pack("vvvv") hds = header + data + string print(hds) end def write_number(row,col,num) raise OutOfRangeException if row > RowMax raise OutOfRangeException if col > ColMax name = 0x0203 len = 0x000E xf = 0x0000 header = [name,len].pack("vv") data = [row,col,xf].pack("vvv") xld = [num].pack("d") xld = xld.to_s.reverse if @big_endian? hdx = header + data + xld print(hdx) end end end