@@ -14,19 +14,24 @@ module Hledger.Cli.CompoundBalanceCommand (
1414 ,compoundBalanceCommand
1515) where
1616
17+ import Data.Maybe (fromMaybe , mapMaybe , maybeToList )
18+ import Data.List.NonEmpty (NonEmpty ((:|) ))
19+ import Data.Bifunctor (second )
20+ import qualified Data.Map as Map
1721import qualified Data.List as List
18- import Data.Maybe ( fromMaybe , mapMaybe )
22+ import qualified Data.List.NonEmpty as NonEmpty
1923import qualified Data.Text as T
2024import qualified Data.Text.Lazy as TL
2125import qualified Data.Text.Lazy.Builder as TB
2226import Data.Time.Calendar (Day , addDays )
2327import System.Console.CmdArgs.Explicit as C (Mode , flagNone , flagReq )
28+ import qualified System.IO as IO
29+ import Hledger.Write.Ods (printFods )
2430import Hledger.Write.Csv (CSV , printCSV , printTSV )
25- import Hledger.Write.Html.Attribute ( stylesheet , tableStyle , alignleft , alignright )
26- import qualified Hledger.Write.Html.Lucid as Html
31+ import Hledger.Write.Html.Lucid ( printHtml )
32+ import Hledger.Write.Html.Attribute ( stylesheet , tableStyle , alignleft )
2733import qualified Hledger.Write.Spreadsheet as Spr
2834import Lucid as L hiding (value_ )
29- import Safe (tailDef )
3035import Text.Tabular.AsciiWide as Tabular hiding (render )
3136
3237import Hledger
@@ -197,6 +202,10 @@ compoundBalanceCommand CompoundBalanceCommandSpec{..} opts@CliOpts{reportspec_=r
197202 " csv" -> printCSV . compoundBalanceReportAsCsv ropts'
198203 " tsv" -> printTSV . compoundBalanceReportAsCsv ropts'
199204 " html" -> L. renderText . compoundBalanceReportAsHtml ropts'
205+ " fods" -> printFods IO. localeEncoding .
206+ fmap (second NonEmpty. toList) . uncurry Map. singleton .
207+ compoundBalanceReportAsSpreadsheet
208+ oneLineNoCostFmt " Account" (Just " " ) ropts'
200209 " json" -> toJsonText
201210 x -> error' $ unsupportedOutputFormatError x
202211
@@ -302,99 +311,85 @@ compoundBalanceReportAsText ropts (CompoundPeriodicReport title _colspans subrep
302311-- subreport title row, and an overall title row, one headings row, and an
303312-- optional overall totals row is added.
304313compoundBalanceReportAsCsv :: ReportOpts -> CompoundPeriodicReport DisplayName MixedAmount -> CSV
305- compoundBalanceReportAsCsv ropts (CompoundPeriodicReport title colspans subreports totalrow) =
306- addtotals $
307- padRow title
308- : ( " Account"
309- : [" Commodity" | layout_ ropts == LayoutBare ]
310- ++ map (reportPeriodName (balanceaccum_ ropts) colspans) colspans
311- ++ (if multiBalanceHasTotalsColumn ropts then [" Total" ] else [] )
312- ++ (if average_ ropts then [" Average" ] else [] )
313- )
314- : concatMap (subreportAsCsv ropts) subreports
315- where
316- -- | Add a subreport title row and drop the heading row.
317- subreportAsCsv ropts1 (subreporttitle, multibalreport, _) =
318- padRow subreporttitle :
319- tailDef [] (multiBalanceReportAsCsv ropts1 multibalreport)
320- padRow s = take numcols $ s : repeat " "
321- where
322- numcols
323- | null subreports = 1
324- | otherwise =
325- (1 + ) $ -- account name column
326- (if layout_ ropts == LayoutBare then (1 + ) else id ) $
327- (if multiBalanceHasTotalsColumn ropts then (1 + ) else id ) $
328- (if average_ ropts then (1 + ) else id ) $
329- maximum $ -- depends on non-null subreports
330- map (length . prDates . second3) subreports
331- addtotals
332- | no_total_ ropts || length subreports == 1 = id
333- | otherwise = (++ map (" Net:" : ) (multiBalanceRowAsCsvText ropts colspans totalrow))
314+ compoundBalanceReportAsCsv ropts cbr =
315+ let spreadsheet =
316+ snd $ snd $
317+ compoundBalanceReportAsSpreadsheet
318+ machineFmt " Account" Nothing ropts cbr
319+ in Spr. rawTableContent $
320+ Spr. horizontalSpan (NonEmpty. head spreadsheet)
321+ (Spr. headerCell (cbrTitle cbr)) :
322+ NonEmpty. toList spreadsheet
334323
335324-- | Render a compound balance report as HTML.
336325compoundBalanceReportAsHtml :: ReportOpts -> CompoundPeriodicReport DisplayName MixedAmount -> Html ()
337326compoundBalanceReportAsHtml ropts cbr =
327+ let (title, (_fixed, cells)) =
328+ compoundBalanceReportAsSpreadsheet
329+ oneLineNoCostFmt " " (Just nbsp) ropts cbr
330+ colspanattr = colspan_ $ T. pack $ show $ length $ NonEmpty. head cells
331+ in do
332+ link_ [rel_ " stylesheet" , href_ " hledger.css" ]
333+ style_ $ stylesheet $
334+ tableStyle ++ [
335+ (" td:nth-child(1)" , " white-space:nowrap" ),
336+ (" tr:nth-child(odd) td" , " background-color:#eee" )
337+ ]
338+ table_ $ do
339+ tr_ $ th_ [colspanattr, style_ alignleft] $ h2_ $ toHtml title
340+ printHtml $ NonEmpty. toList $ fmap (map (fmap L. toHtml)) cells
341+
342+ -- | Render a compound balance report as Spreadsheet.
343+ compoundBalanceReportAsSpreadsheet ::
344+ AmountFormat -> T. Text -> Maybe T. Text ->
345+ ReportOpts -> CompoundPeriodicReport DisplayName MixedAmount ->
346+ (T. Text , ((Maybe Int , Maybe Int ), NonEmpty [Spr. Cell Spr. NumLines T. Text ]))
347+ compoundBalanceReportAsSpreadsheet fmt accountLabel maybeBlank ropts cbr =
338348 let
339349 CompoundPeriodicReport title colspans subreports totalrow = cbr
340350 headerrow =
341- th_ " " :
342- (guard (layout_ ropts == LayoutBare ) >> [th_ " Commodity" ]) ++
343- map (th_ [style_ alignright] . toHtml .
344- reportPeriodName (balanceaccum_ ropts) colspans)
351+ Spr. headerCell accountLabel :
352+ (guard (layout_ ropts == LayoutBare ) >> [Spr. headerCell " Commodity" ]) ++
353+ map (Spr. headerCell . reportPeriodName (balanceaccum_ ropts) colspans)
345354 colspans ++
346- (guard (multiBalanceHasTotalsColumn ropts) >> [th_ " Total" ]) ++
347- (guard (average_ ropts) >> [th_ " Average" ])
355+ (guard (multiBalanceHasTotalsColumn ropts) >> [Spr. headerCell " Total" ]) ++
356+ (guard (average_ ropts) >> [Spr. headerCell " Average" ])
348357
349- colspanattr = colspan_ $ T. pack $ show $ length headerrow
350- leftattr = style_ alignleft
351- blankrow = tr_ $ td_ [colspanattr] $ toHtmlRaw (" " :: String )
352-
353- titlerows =
354- [tr_ $ th_ [colspanattr, leftattr] $ h2_ $ toHtml title
355- ,tr_ $ mconcat headerrow
356- ]
358+ blankrow =
359+ fmap (Spr. horizontalSpan headerrow . Spr. defaultCell) maybeBlank
357360
358361 -- Make rows for a subreport: its title row, not the headings row,
359362 -- the data rows, any totals row, and a blank row for whitespace.
360- subreportrows :: (T. Text , MultiBalanceReport , Bool ) -> [Html () ]
363+ subreportrows ::
364+ (T. Text , MultiBalanceReport , Bool ) -> [[Spr. Cell Spr. NumLines T. Text ]]
361365 subreportrows (subreporttitle, mbr, _increasestotal) =
362366 let
363- -- TODO: should the commodity_column be displayed as a subaccount in this case as well?
364367 (_, bodyrows, mtotalsrows) =
365- multiBalanceReportAsSpreadsheetParts oneLineNoCostFmt ropts mbr
366- formatRow = Html. formatRow . map (fmap L. toHtml)
368+ multiBalanceReportAsSpreadsheetParts fmt ropts mbr
367369
368370 in
369- [tr_ $ th_ [colspanattr, leftattr, class_ " account" ] $ toHtml subreporttitle]
370- ++ map formatRow bodyrows
371- ++ map formatRow mtotalsrows
372- ++ [blankrow]
371+ Spr. horizontalSpan headerrow
372+ ((Spr. defaultCell subreporttitle){
373+ Spr. cellStyle = Spr. Body Spr. Total ,
374+ Spr. cellClass = Spr. Class " account"
375+ }) :
376+ bodyrows ++
377+ mtotalsrows ++
378+ maybeToList blankrow ++
379+ []
373380
374381 totalrows =
375382 if no_total_ ropts || length subreports == 1 then []
376383 else
377- multiBalanceRowAsCellBuilders oneLineNoCostFmt ropts colspans
384+ multiBalanceRowAsCellBuilders fmt ropts colspans
378385 Total simpleDateSpanCell totalrow
379386 -- make a table of rendered lines of the report totals row
380387 & map (map (fmap wbToText))
381388 & Spr. addRowSpanHeader
382389 ((Spr. defaultCell " Net:" ) {Spr. cellClass = Spr. Class " account" })
383390 -- insert a headings column, with Net: on the first line only
384- & addTotalBorders -- marking the first for special styling
385- & map (Html. formatRow . map (fmap L. toHtml))
386- -- convert to a list of HTML totals rows
387-
388- in do
389- link_ [rel_ " stylesheet" , href_ " hledger.css" ]
390- style_ $ stylesheet $
391- tableStyle ++ [
392- (" td:nth-child(1)" , " white-space:nowrap" ),
393- (" tr:nth-child(even) td" , " background-color:#eee" )
394- ]
395- table_ $ mconcat $
396- titlerows
397- ++ [blankrow]
398- ++ concatMap subreportrows subreports
399- ++ totalrows
391+ & addTotalBorders -- marking the first row for special styling
400392
393+ in (title,
394+ ((Just 1 , Just 1 ),
395+ headerrow :| concatMap subreportrows subreports ++ totalrows))
0 commit comments