Question: Is there a correct way to add a total or summary row?
Opened this issue · 2 comments
Hello,
I'm trying to add a total row by adding up values from the results, something like this in my class
def results
original_results = super
total_value = original_results.rows.map {|row| row.last.to_f}.sum.round(2)
original_results.rows << ['Total', total_value.to_s]
original_results
end
This somewhat works however now my report has 2 additional rows:
Total 4546.1
Total 9092.2
The first one is correct, the second is exactly double. Is there a recommended way of adding a total or summary row? Thanks for the help.
@hughkelsey I'm not sure why your example doesn't work (all I've done is read it), but if I recall correctly, I think I once did totals by doing a UNION query to add a row to the SQL results and giving Dossier a footer parameter of 1, so that it renders the last 1 row of SQL results as a footer.
Does that make sense?
I do like your idea of doing it in Ruby, though. If you want to debug what's happening in your example, bundle open dossier
will let you add puts
statements or whatever, and gem pristine dossier
will clean up for you when you're done.
In case anyone faces this issue, the problem seems to be that report.results
gets called 4 times in the report show, which adds a row each time and recalculates the sum for all previous rows. I found two ways to get around the issue:
- Call
report.results
only once in the report show, save the result in a temp variable- res = report.results
, and use that to render the report. - Use an if statement to stop adding rows once the first one was added
def results
original_results = super
unless original_results.rows.last[0] == 'Total'
total_value = original_results.rows.map {|row| row.last.to_f}.sum.round(2)
original_results.rows << ['Total', total_value.to_s]
end
original_results
end
Neither of those two solutions seems particularly elegant. I tried using report.results.body
and report.results.footers
to do the calculation instead but that didn't work since the gem automatically assigns the last N rows as footers then puts whatever is left in the body.
It could be worth considering a way to add N empty footers which the user can then fill as needed instead of splitting one dataset between body and footers.