Skip to content

Commit

Permalink
'init'
Browse files Browse the repository at this point in the history
  • Loading branch information
stevo committed Oct 11, 2009
0 parents commit 75a1d34
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
.idea/**/*
Empty file added README
Empty file.
1 change: 1 addition & 0 deletions init.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'excellent'
1 change: 1 addition & 0 deletions install.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Install hook code here
7 changes: 7 additions & 0 deletions lib/excellent.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'excellent/base_overrides'
require 'excellent/template_handler'

Mime::Type.register "application/vnd.ms-excel", :xls

ActionView::Template.register_template_handler :xerb, ActionView::TemplateHandlers::XERB

10 changes: 10 additions & 0 deletions lib/excellent/base_overrides.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#Changes keys of hash accordig to given map
# >> {:a => 10, :c => 20}.map_keys({:a => :b})
# => {:c=>20, :b=>10}
class Hash
def map_keys(hsh)
returning Hash.new do |r|
each{|k,v| r[hsh[k] || k] = v}
end
end
end
1 change: 1 addition & 0 deletions lib/excellent/template_handler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require 'excellent/xerb'
24 changes: 24 additions & 0 deletions lib/excellent/xerb.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#require 'erb'
require 'excellent/xhtml2xls'

module ActionView
module TemplateHandlers
class XERB < ERB
include Compilable

cattr_accessor :erb_trim_mode
self.erb_trim_mode = '-'

def compile(template)
src = %{
ts = %{#{template.source}}
xhtml = self.render(:inline => ts, :type => :erb )
h2x = Hsh2Xls.new(xhtml)
h2x.output
}

RUBY_VERSION >= '1.9' ? src.sub(/\A#coding:.*\n/, '') : src
end
end
end
end
127 changes: 127 additions & 0 deletions lib/excellent/xhtml2xls.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@


class XlsCellStyle
attr_reader :raw_style, :style

ATTRIBUTES_MAP = {
"font-weight" => :weight,
"color" => :color,
"font-size" => :size
}

def initialize(style)
return nil unless style
@raw_style = style.gsub(' ','')
@style = Spreadsheet::Format.new(style2hsh)
end

def style2hsh
attrs = @raw_style.split(';')
attrs.inject({}){|acc, attr| acc.merge(encode_attribute(attr))}
end

def encode_attribute(attribute)
attr,value = attribute.split(':')

value = case attr
when "color" then value.to_sym
when "font-size" then value.to_i
when "font-weight" then value.to_sym
end

return Hash[attr,value].map_keys(ATTRIBUTES_MAP)
end

end

class XlsCell

attr_reader :data

def initialize(cell,kind='normal')
if cell.is_a? Hash
cell.symbolize_keys!
@data = cell[:content] || ''
@style = XlsCellStyle.new(cell[:style])
else
@data = cell || ''
@style = nil
end
end

def style
@style ? @style.style : nil
end

end

class XlsRow
attr_reader :cells

def initialize(row)
kind = row.keys.include?(:th) ? 'header' : 'normal'
@cells = row.values.sum.map{|c| XlsCell.new(c,kind)}
end

end

class XlsTable
attr_reader :rows

def initialize(hsh)
@rows = hsh[:tr].map{|tr| XlsRow.new(tr)}
end

end

class Hsh2Xls
require 'spreadsheet'
require 'xmlsimple'

attr_reader :xhtml

REQUIRED_FIRST_LEVEL_KEYS = [:name, :tr]

def initialize(xhtml)
@xhtml = xhtml
@hsh = XmlSimple.xml_in(@xhtml, {'ForceArray' => true}).symbolize_keys
validate_hash
end

private

def validate_hash
#TODO To rewrite
raise "Table has to have 'name' attribute and a set of rows" if !(REQUIRED_FIRST_LEVEL_KEYS-@hsh.keys ).empty?
raise "tr is to be array" unless @hsh[:tr].kind_of?(Array)
end

def render_xls
xls = Spreadsheet::Workbook.new
@sheet = xls.create_worksheet :name => @hsh[:name]

xls_table = XlsTable.new(@hsh)

xls_table.rows.each_with_index do |row, row_idx|
row.cells.each_with_index do |cell, cell_idx|
render_cell(row_idx, cell_idx, cell)
end
end

xls_output = StringIO.new
xls.write xls_output
return xls_output.string
end

def render_cell(row_idx, cell_idx, cell)
@sheet.row(row_idx).set_format(cell_idx, cell.style) if cell.style
@sheet[row_idx, cell_idx] = cell.data
end

public

def output
render_xls
end

end

0 comments on commit 75a1d34

Please sign in to comment.