Skip to content

Commit

Permalink
Use axlsx add_style for formatting
Browse files Browse the repository at this point in the history
Simplified DSL context handling
Version bump to 1.0.1
  • Loading branch information
glebm committed Dec 4, 2012
1 parent 81e04d7 commit b6c0f02
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 104 deletions.
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -10,4 +10,5 @@ group :test, :development do
gem 'haml'
gem 'RedCloth'
gem 'debugger', platform: :ruby
gem 'ruby-debug', platform: :jruby
end
6 changes: 2 additions & 4 deletions lib/to_spreadsheet.rb
@@ -1,9 +1,7 @@
require 'nokogiri'
require 'to_spreadsheet/action_pack_renderers'
require 'to_spreadsheet/mime_types'
require 'to_spreadsheet/version'
require 'to_spreadsheet/helpers'
require 'to_spreadsheet/context'
require 'to_spreadsheet/renderer'
require 'to_spreadsheet/railtie' if defined?(Rails)

module ToSpreadsheet
class << self
Expand Down
20 changes: 18 additions & 2 deletions lib/to_spreadsheet/context.rb
Expand Up @@ -17,10 +17,26 @@ class << self
def global
@global ||= new
end

def current
Thread.current[:_to_spreadsheet_ctx]
end

def current=(ctx)
Thread.current[:_to_spreadsheet_ctx] = ctx
end

def with_context(ctx, &block)
old = current
self.current = ctx
r = block.call(ctx)
self.current = old
r
end
end

def initialize(wb_options = nil)
@rules = []
@rules = []
workbook wb_options if wb_options
end

Expand Down Expand Up @@ -83,7 +99,7 @@ def add_rule(rule_type, selector_type, selector_value, options = {})

# A new context
def merge(other_context)
ctx = Context.new()
ctx = Context.new()
ctx.rules = rules + other_context.rules
ctx
end
Expand Down
19 changes: 0 additions & 19 deletions lib/to_spreadsheet/helpers.rb

This file was deleted.

@@ -1,32 +1,24 @@
require 'active_support'
require 'action_controller/metal/renderers'
require 'action_controller/metal/responder'

require 'to_spreadsheet/renderer'

# This will let us do thing like `render :xlsx => 'index'`
# This is similar to how Rails internally implements its :json and :xml renderers
ActionController::Renderers.add :xlsx do |template, options|
filename = options[:filename] || options[:template] || 'data'

html = with_context ToSpreadsheet::Context.global.merge(ToSpreadsheet::Context.new) do
# local context
@local_formats.each do |selector, &block|
context.process_dsl selector, &block
end if @local_formats
render_to_string(options[:template], options)
end

data = ToSpreadsheet::Axlsx::Renderer.to_data(html)
send_data data, type: :xlsx, disposition: %(attachment; filename="#{filename}.xlsx")
end

class ActionController::Responder
# This sets up a default render call for when you do
# respond_to do |format|
# format.xlsx
# end
def to_xlsx
controller.render xlsx: controller.action_name
end
end
require 'active_support'
require 'action_controller/metal/renderers'
require 'action_controller/metal/responder'

# This will let us do thing like `render :xlsx => 'index'`
# This is similar to how Rails internally implements its :json and :xml renderers
ActionController::Renderers.add :xlsx do |template, options|
filename = options[:filename] || options[:template] || 'data'
data = ToSpreadsheet::Context.with_context ToSpreadsheet::Context.global.merge(ToSpreadsheet::Context.new) do |context|
html = render_to_string(template, options.merge(template: template, formats: ['html']))
ToSpreadsheet::Renderer.to_data(html, context)
end
send_data data, type: :xlsx, disposition: %(attachment; filename="#{filename}.xlsx")
end

class ActionController::Responder
# This sets up a default render call for when you do
# respond_to do |format|
# format.xlsx
# end
def to_xlsx
controller.render xlsx: controller.action_name
end
end
@@ -1,2 +1,2 @@
require 'action_dispatch/http/mime_type'
Mime::Type.register "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", :xlsx unless Mime::Type.lookup_by_extension(:xlsx)
require 'action_dispatch/http/mime_type'
Mime::Type.register "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", :xlsx unless Mime::Type.lookup_by_extension(:xlsx)
11 changes: 11 additions & 0 deletions lib/to_spreadsheet/rails/view_helpers.rb
@@ -0,0 +1,11 @@
module ToSpreadsheet
module Rails
module ViewHelpers
def format_xls(selector = nil, &block)
ctx = ToSpreadsheet::Context.current
return unless ctx
ctx.format_xls selector, &block
end
end
end
end
11 changes: 11 additions & 0 deletions lib/to_spreadsheet/railtie.rb
@@ -0,0 +1,11 @@
require 'rails/railtie'
require 'to_spreadsheet/rails/mime_types'
require 'to_spreadsheet/rails/action_pack_renderers'
require 'to_spreadsheet/rails/view_helpers'
module ToSpreadsheet
class Railtie < ::Rails::Railtie
initializer "to_spreadsheet.view_helpers" do
ActionView::Base.send :include, ToSpreadsheet::Rails::ViewHelpers
end
end
end
30 changes: 13 additions & 17 deletions lib/to_spreadsheet/renderer.rb
@@ -1,34 +1,30 @@
require 'axlsx'
require 'nokogiri'

module ToSpreadsheet
module Renderer
extend self

def to_stream(html, local_context = nil)
to_package(html, local_context).to_stream
def to_stream(html, context = nil)
to_package(html, context).to_stream
end

def to_data(html, local_context = nil)
to_package(html, local_context).to_stream.read
def to_data(html, context = nil)
to_package(html, context).to_stream.read
end

def to_package(html, local_context = nil)
with_context init_context(local_context) do
package = build_package(html, context)
context.rules.each do |rule|
puts "Applying #{rule}"
rule.apply(context, package)
end
package
def to_package(html, context = nil)
context ||= ToSpreadsheet::Context.global.merge(Context.new)
package = build_package(html, context)
context.rules.each do |rule|
#Rails.logger.debug "Applying #{rule}"
rule.apply(context, package)
end
package
end

private

def init_context(local_context)
local_context ||= ToSpreadsheet::Context.new
ToSpreadsheet::Context.global.merge local_context
end

def build_package(html, context)
package = ::Axlsx::Package.new
spreadsheet = package.workbook
Expand Down
21 changes: 7 additions & 14 deletions lib/to_spreadsheet/rule/format.rb
Expand Up @@ -5,10 +5,11 @@ module Rule
class Format < Base
include ::ToSpreadsheet::TypeFromValue
def apply(context, sheet)
wb = sheet.workbook
case selector_type
when :css
css_match selector_query, context.to_xml_node(sheet) do |xml_node|
apply_inline_styles context, context.to_xls_entity(xml_node)
add_and_apply_style wb, context, context.to_xls_entity(xml_node)
end
when :row
sheet.row_style selector_query, options if options.present?
Expand All @@ -17,7 +18,7 @@ def apply(context, sheet)
sheet.col_style selector_query, inline_styles if inline_styles.present?
apply_col_info sheet.column_info[selector_query]
when :range
apply_inline_styles range_match(selector_type, sheet), context
add_and_apply_style wb, range_match(selector_type, sheet), context
end
end

Expand All @@ -32,7 +33,7 @@ def apply_col_info(col_info)
end
end

def apply_inline_styles(context, xls_ent)
def add_and_apply_style(wb, context, xls_ent)
# Custom format rule
# format 'td.sel', lambda { |node| ...}
if self.options.is_a?(Proc)
Expand All @@ -47,17 +48,9 @@ def apply_inline_styles(context, xls_ent)
options[k] = context.instance_exec(xls_ent, &v) if v.is_a?(Proc)
end

# Apply inline styles
options.each do |k, v|
next if v.nil?
setter = :"#{k}="
xls_ent.send setter, v if xls_ent.respond_to?(setter)
if xls_ent.respond_to?(:cells)
xls_ent.cells.each do |cell|
cell.send setter, v if cell.respond_to?(setter)
end
end
end
style = wb.styles.add_style options
cells = xls_ent.respond_to?(:cells) ? xls_ent.cells : [xls_ent]
cells.each { |cell| cell.style = style }
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions lib/to_spreadsheet/version.rb
@@ -1,3 +1,3 @@
module ToSpreadsheet
VERSION = '1.0.0'
end
module ToSpreadsheet
VERSION = '1.0.1'
end
7 changes: 5 additions & 2 deletions spec/format_spec.rb
Expand Up @@ -6,7 +6,7 @@
:ruby
format_xls do
format column: 0, width: 25
format 'tr', color: lambda { |row| 'cccccc' if row.index.odd? }
format 'tr', fg_color: lambda { |row| 'cccccc' if row.index.odd? }
end
%table
%tr
Expand All @@ -23,7 +23,10 @@
sheet.column_info[0].width.should == 25
end
it 'runs lambdas' do
sheet.rows[1].cells[0].color.rgb.should == Axlsx::Color.new(rgb: 'cccccc').rgb
cell = sheet.rows[1].cells[0]
styles = sheet.workbook.styles
font_id = styles.cellXfs[cell.style].fontId
styles.fonts[font_id].color.rgb.should == Axlsx::Color.new(rgb: 'cccccc').rgb
end
end
end
27 changes: 18 additions & 9 deletions spec/spec_helper.rb
Expand Up @@ -4,15 +4,24 @@
require 'to_spreadsheet'
require 'haml'

RSpec.configure do |config|
include ToSpreadsheet::Helpers

module TestRendering
def build_spreadsheet(src = {})
haml = if src[:haml]
src[:haml]
elsif src[:file]
File.read(File.expand_path "support/#{src[:file]}", File.dirname(__FILE__))
end
ToSpreadsheet::Context.with_context ToSpreadsheet::Context.global.merge(ToSpreadsheet::Context.new) do |context|
html = Haml::Engine.new(haml).render(self)
ToSpreadsheet::Renderer.to_package(html, context)
end
end
end

def build_spreadsheet(src = {})
haml = if src[:haml]
src[:haml]
elsif src[:file]
File.read(File.expand_path "support/#{src[:file]}", File.dirname(__FILE__))
end
ToSpreadsheet::Renderer.to_package(Haml::Engine.new(haml).render)

require 'to_spreadsheet/rails/view_helpers'
RSpec.configure do |config|
include TestRendering
include ::ToSpreadsheet::Rails::ViewHelpers
end

0 comments on commit b6c0f02

Please sign in to comment.