So here's what I started with, after reading the docs for the spreadsheet library. Basically this is the creation of one report:
require 'spreadsheet'
class Reporter
public
class << self
def report_all_transactions(district)
book = Spreadsheet::Workbook.new
sheet = book.create_worksheet
sheet.row(1).concat ["ALL TRANSACTIONS BY THERAPIST"]
index = 2
district.therapists.each do |t|
sheet.row(index).concat [t.full_name]
index += 1
sheet.row(index).concat ["ID","Date","Start",
"Stop","Status","Location"]
index += 1
district.transactions.each do |trans|
sheet.row(index).concat [trans.id,trans.date,
trans.start,trans.stop,
trans.status,trans.school.name]
index += 1
end
index += 2
end
book.write "#{RAILS_ROOT}/public/data/all_transactions_report.xls"
end
end
end
It's not bad on the whole, but it's a little wordy, and the one thing that REALLY bothered me about it was that index tracking I was having to do and the repetitive nature of the whole "add some data, increment the index" thing.
So, in order to make this spreadsheet library more pleasant to work with, I created the class below:
class SheetWrapper
attr_accessor :index
def initialize(worksheet)
@sheet = worksheet
@index = 0
end
def add_row(array)
@sheet.row(@index).concat array
@index += 1
end
def add_lines(count)
@index += count
end
end
It's pretty simple, just a couple methods, but look what it does to that first code example I showed:
require 'spreadsheet'
class Reporter
public
class << self
def report_all_transactions_by_date(district)
book = Spreadsheet::Workbook.new
sheet = SheetWrapper.new(book.create_worksheet)
sheet.add_row ["ALL TRANSACTIONS BY THERAPIST"]
sheet.add_lines(1)
district.therapists.each do |t|
sheet.add_row [t.full_name]
sheet.add_row ["ID","Date","Start",
"Stop","Status","Location"]
district.transactions.each do |trans|
sheet.add_row [trans.id,trans.date,
trans.start,trans.stop,
trans.status,trans.school.name]
end
sheet.add_lines(2)
end
book.write "#{RAILS_ROOT}/public/data/all_transactions_report.xls"
end
end
end
Better already. One more problem that I had, though, was that all my report methods were kind of following the same pattern of opening a work book, adding some data, and then writing it out to the data directory. In order to reduce that pattern down to one chunk of reusable code, I extracted the "run_report" method as follows:
require 'spreadsheet'
class Reporter
public
class << self
def report_all_transactions_by_date(district)
filename = "all_transactions"
self.run_report(filename,"ALL TRANSACTIONS") do |sheet|
district.therapists.each do |t|
sheet.add_row [t.full_name]
sheet.add_row ["ID","Date","Start","Stop","Status","Location"]
district.transactions.each do |trans|
sheet.add_row [trans.id,trans.date,
trans.start,trans.stop,
trans.status,trans.school.name]
end
sheet.add_lines 2
end
end
end
end
protected
class << self
def run_report(file_name,title,header_row = nil)
name = "#{file_name}.xls"
book = Spreadsheet::Workbook.new
sheet = SheetWrapper.new(book.create_worksheet)
sheet.add_row [title]
sheet.index = 2
sheet.add_row header_row if header_row
yield(sheet)
book.write "#{RAILS_ROOT}/public/data/#{name}"
end
end
end
And that's pretty much it. Now all the large reports can be generated as Excel files, and the users are happy because they can play with that data anyway they need to in order to extract the information they're looking for (and we didn't have to spend a month writing features that spreadsheet programs already have into our web app).
![[image]](http://mowser.com/img?url=http%3A%2F%2Fimg2.blogblog.com%2Fimg%2Fwidgets%2Farrow_dropdown.gif)
![[image]](http://mowser.com/img?url=http%3A%2F%2Fimg1.blogblog.com%2Fimg%2Fwidgets%2Fsubscribe-google.png)
![[image]](http://mowser.com/img?url=http%3A%2F%2Fimg1.blogblog.com%2Fimg%2Fwidgets%2Fsubscribe-bloglines.png)
![[image]](http://mowser.com/img?url=http%3A%2F%2Fimg1.blogblog.com%2Fimg%2Fwidgets%2Fsubscribe-netvibes.png)
![[image]](http://mowser.com/img?url=http%3A%2F%2Fimg1.blogblog.com%2Fimg%2Fwidgets%2Fsubscribe-newsgator.png)
![[image]](http://mowser.com/img?url=http%3A%2F%2Fimg1.blogblog.com%2Fimg%2Fwidgets%2Fsubscribe-yahoo.png)
