@@ -308,7 +308,7 @@ import Hledger.Write.Ods (printFods)
308308import Hledger.Write.Html (Html , styledTableHtml , htmlAsLazyText , toHtml )
309309import Hledger.Write.Spreadsheet (rawTableContent , headerCell ,
310310 addHeaderBorders , addRowSpanHeader ,
311- cellFromMixedAmount , cellsFromMixedAmount )
311+ cellFromMixedAmount , cellsFromMixedAmount , cellFromAmount )
312312import Hledger.Write.Spreadsheet qualified as Ods
313313
314314
@@ -635,6 +635,9 @@ renderComponent topaligned oneline opts (acctname, dep, total) (FormatField ljus
635635 }
636636
637637
638+ headerWithoutBorders :: [Ods. Cell () text ] -> [Ods. Cell Ods. NumLines text ]
639+ headerWithoutBorders = map (\ c -> c {Ods. cellBorder = Ods. noBorder})
640+
638641simpleDateSpanCell :: PeriodTitles -> DateSpan -> Ods. Cell Ods. NumLines Text
639642simpleDateSpanCell ph = Ods. defaultCell . renderPeriodHeading ph
640643
@@ -663,8 +666,11 @@ balanceReportAsSpreadsheet fmt opts (items, total) =
663666 headers =
664667 addHeaderBorders $ map headerCell $
665668 " account" : case layout_ opts of
669+ LayoutBareWide -> allCommodities
666670 LayoutBare -> [" commodity" , " balance" ]
667671 _ -> [" balance" ]
672+ allCommodities =
673+ S. toAscList $ foldMap (\ (_,_,_,ma) -> maCommodities ma) items
668674 rows ::
669675 RowClass -> BalanceReportItem ->
670676 [[Ods. Cell Ods. NumLines Text ]]
@@ -678,6 +684,15 @@ balanceReportAsSpreadsheet fmt opts (items, total) =
678684 Value -> renderBalanceAcct opts nbsp (name, dispName, dep) in
679685 addRowSpanHeader accountCell $
680686 case layout_ opts of
687+ LayoutBareWide ->
688+ let bopts =
689+ machineFmt {
690+ displayCommodity = False ,
691+ displayCommodityOrder = Just allCommodities
692+ } in
693+ [map (\ bldAmt ->
694+ fmap wbToText $ cellFromAmount bopts (amountClass rc, bldAmt)) $
695+ showMixedAmountLinesPartsB bopts ma]
681696 LayoutBare ->
682697 map (\ a -> [cell $ acommodity a, renderAmount rc $ mixedAmount a])
683698 . amounts $ mixedAmountStripCosts ma
@@ -701,29 +716,41 @@ balanceReportAsSpreadsheet fmt opts (items, total) =
701716multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
702717multiBalanceReportAsCsv opts@ ReportOpts {.. } report =
703718 (if transpose_ then transpose else id ) $
704- rawTableContent $ header : body ++ totals
719+ rawTableContent $ header ++ body ++ totals
705720 where
706721 (header, body, totals) =
707- multiBalanceReportAsSpreadsheetParts machineFmt opts report
722+ multiBalanceReportAsSpreadsheetParts machineFmt opts
723+ (allCommoditiesFromPeriodicReport $ prRows report) report
708724
709725-- | Render the Spreadsheet table rows (CSV, ODS, HTML) for a MultiBalanceReport.
710726-- Returns the heading row, 0 or more body rows, and the totals row if enabled.
711727multiBalanceReportAsSpreadsheetParts ::
712- AmountFormat -> ReportOpts -> MultiBalanceReport ->
713- ([Ods. Cell Ods. NumLines Text ],
728+ AmountFormat -> ReportOpts ->
729+ [CommoditySymbol ] -> MultiBalanceReport ->
730+ ([[Ods. Cell Ods. NumLines Text ]],
714731 [[Ods. Cell Ods. NumLines Text ]],
715732 [[Ods. Cell Ods. NumLines Text ]])
716- multiBalanceReportAsSpreadsheetParts fmt opts@ ReportOpts {.. } (PeriodicReport colspans items tr) =
717- (headers, concatMap fullRowAsTexts items, addTotalBorders totalrows)
733+ multiBalanceReportAsSpreadsheetParts fmt opts@ ReportOpts {.. }
734+ allCommodities (PeriodicReport colspans items tr) =
735+ (allHeaders, concatMap fullRowAsTexts items, addTotalBorders totalrows)
718736 where
719737 accountCell label =
720738 (Ods. defaultCell label) {Ods. cellClass = Ods. Class " account" }
721739 hCell cls label = (headerCell label) {Ods. cellClass = Ods. Class cls}
740+ allHeaders =
741+ case layout_ of
742+ LayoutBareWide ->
743+ [headerWithoutBorders $
744+ Ods. emptyCell :
745+ concatMap (Ods. horizontalSpan allCommodities) dateHeaders,
746+ headers]
747+ _ -> [headers]
722748 headers =
723749 addHeaderBorders $
724750 hCell " account" " account" :
725751 case layout_ of
726752 LayoutTidy -> map headerCell tidyColumnLabels
753+ LayoutBareWide -> dateHeaders >> map headerCell allCommodities
727754 LayoutBare -> headerCell " commodity" : dateHeaders
728755 _ -> dateHeaders
729756 dateHeaders =
@@ -744,7 +771,7 @@ multiBalanceReportAsSpreadsheetParts fmt opts@ReportOpts{..} (PeriodicReport col
744771 rowAsText Total (simpleDateSpanCell period_titles_) tr
745772 rowAsText rc dsCell =
746773 map (map (fmap wbToText)) .
747- multiBalanceRowAsCellBuilders fmt opts colspans rc dsCell
774+ multiBalanceRowAsCellBuilders fmt opts colspans allCommodities rc dsCell
748775
749776tidyColumnLabels :: [Text ]
750777tidyColumnLabels =
@@ -764,10 +791,12 @@ multiBalanceReportAsSpreadsheet ::
764791 ((Int , Int ), [[Ods. Cell Ods. NumLines Text ]])
765792multiBalanceReportAsSpreadsheet ropts mbr =
766793 let (header,body,total) =
767- multiBalanceReportAsSpreadsheetParts oneLineNoCostFmt ropts mbr
794+ multiBalanceReportAsSpreadsheetParts oneLineNoCostFmt ropts
795+ (allCommoditiesFromPeriodicReport $ prRows mbr) mbr
768796 in (if transpose_ ropts then swap *** Ods. transpose else id ) $
769- ((1 , case layout_ ropts of LayoutWide _ -> 1 ; _ -> 0 ),
770- header : body ++ total)
797+ ((case layout_ ropts of LayoutBareWide -> 2 ; _ -> 1 ,
798+ case layout_ ropts of LayoutWide _ -> 1 ; _ -> 0 ),
799+ header ++ body ++ total)
771800
772801
773802-- | Render a multi-column balance report as plain text suitable for console output.
@@ -839,10 +868,20 @@ multiBalanceReportAsTable opts@ReportOpts{summary_only_, average_, balanceaccum_
839868 (Group multiColumnTableInterColumnBorder $ map Header colheadings)
840869 (concat rows)
841870 where
842- colheadings = [" Commodity" | layout_ opts == LayoutBare ]
843- ++ (if not summary_only_ then map (reportPeriodName (period_titles_ opts) balanceaccum_ spans) spans else [] )
844- ++ [" Total" | multiBalanceHasTotalsColumn opts]
845- ++ [" Average" | average_]
871+ colheadings =
872+ [" Commodity" | layout_ opts == LayoutBare ]
873+ ++ (if not summary_only_
874+ then
875+ let spanNames =
876+ map (reportPeriodName (period_titles_ opts) balanceaccum_ spans) spans in
877+ case layout_ opts of
878+ LayoutBareWide ->
879+ liftA2 (\ s c -> T. concat [s, " (" , c, " )" ]) spanNames allCommodities
880+ _ -> spanNames
881+ else [] )
882+ ++ [" Total" | multiBalanceHasTotalsColumn opts]
883+ ++ [" Average" | average_]
884+ allCommodities = allCommoditiesFromPeriodicReport items
846885 (accts, rows) = unzip $ fmap fullRowAsTexts items'
847886 where
848887 isLeaf rs row = not $ any (\ r -> T. isPrefixOf (displayFull (prrName row) <> " :" ) (displayFull (prrName r))) rs
@@ -851,12 +890,12 @@ multiBalanceReportAsTable opts@ReportOpts{summary_only_, average_, balanceaccum_
851890 else items
852891 fullRowAsTexts row = (replicate (length rs) (renderacct row), rs)
853892 where
854- rs = multiBalanceRowAsText opts row
893+ rs = multiBalanceRowAsText opts allCommodities row
855894 renderacct row' = renderPeriodicAcct opts " " row'
856895 addtotalrow
857896 | no_total_ opts = id
858897 | otherwise =
859- let totalrows = multiBalanceRowAsText opts tr
898+ let totalrows = multiBalanceRowAsText opts allCommodities tr
860899 rowhdrs = Group NoLine $ map Header $ totalRowHeadingText : replicate (length totalrows - 1 ) " "
861900 colhdrs = Header [] -- unused, concatTables will discard
862901 in (flip (concatTables SingleLine ) $ Table rowhdrs colhdrs totalrows)
@@ -865,12 +904,17 @@ multiBalanceReportAsTable opts@ReportOpts{summary_only_, average_, balanceaccum_
865904 multiColumnTableInterRowBorder = NoLine
866905 multiColumnTableInterColumnBorder = if pretty_ opts then SingleLine else NoLine
867906
907+ allCommoditiesFromPeriodicReport ::
908+ [PeriodicReportRow a MixedAmount ] -> [CommoditySymbol ]
909+ allCommoditiesFromPeriodicReport =
910+ S. toAscList . foldMap (foldMap maCommodities . prrAmounts)
911+
868912multiBalanceRowAsCellBuilders ::
869- AmountFormat -> ReportOpts -> [DateSpan ] ->
913+ AmountFormat -> ReportOpts -> [DateSpan ] -> [ CommoditySymbol ] ->
870914 RowClass -> (DateSpan -> Ods. Cell Ods. NumLines Text ) ->
871915 PeriodicReportRow a MixedAmount ->
872916 [[Ods. Cell Ods. NumLines WideBuilder ]]
873- multiBalanceRowAsCellBuilders bopts ropts@ ReportOpts {.. } colspans
917+ multiBalanceRowAsCellBuilders bopts ropts@ ReportOpts {.. } colspans allCommodities
874918 rc renderDateSpanCell (PeriodicReportRow _acct as rowtot rowavg) =
875919 case layout_ of
876920 LayoutWide width -> [fmap (cellFromMixedAmount bopts{displayMaxWidth= width}) clsamts]
@@ -881,6 +925,8 @@ multiBalanceRowAsCellBuilders bopts ropts@ReportOpts{..} colspans
881925 . transpose -- each row becomes a list of Text quantities
882926 . map (cellsFromMixedAmount bopts{displayCommodity= False , displayCommodityOrder= Just cs, displayMinWidth= Nothing })
883927 $ clsamts
928+ LayoutBareWide -> [concatMap (cellsFromMixedAmount bopts{displayCommodity= False , displayCommodityOrder= Just allCommodities, displayMinWidth= Nothing })
929+ $ clsamts]
884930 LayoutTidy -> concat
885931 . zipWith (map . addDateColumns) colspans
886932 . map ( zipWith (\ c a -> [wbCell c, a]) cs
@@ -923,16 +969,20 @@ multiBalanceHasTotalsColumn :: ReportOpts -> Bool
923969multiBalanceHasTotalsColumn ropts =
924970 row_total_ ropts && balanceaccum_ ropts `notElem` [Cumulative , Historical ]
925971
926- multiBalanceRowAsText :: ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder ]]
927- multiBalanceRowAsText opts =
972+ multiBalanceRowAsText ::
973+ ReportOpts -> [CommoditySymbol ] -> PeriodicReportRow a MixedAmount -> [[WideBuilder ]]
974+ multiBalanceRowAsText opts allCommodities =
928975 rawTableContent .
929- multiBalanceRowAsCellBuilders oneLineNoCostFmt{displayColour= color_ opts} opts []
976+ multiBalanceRowAsCellBuilders oneLineNoCostFmt{displayColour= color_ opts}
977+ opts [] allCommodities
930978 Value (simpleDateSpanCell $ period_titles_ opts)
931979
932- multiBalanceRowAsCsvText :: ReportOpts -> [DateSpan ] -> PeriodicReportRow a MixedAmount -> [[T. Text ]]
933- multiBalanceRowAsCsvText opts colspans =
980+ multiBalanceRowAsCsvText ::
981+ ReportOpts -> [DateSpan ] -> [CommoditySymbol ] ->
982+ PeriodicReportRow a MixedAmount -> [[T. Text ]]
983+ multiBalanceRowAsCsvText opts colspans allCommodities =
934984 map (map (wbToText . Ods. cellContent)) .
935- multiBalanceRowAsCellBuilders machineFmt opts colspans
985+ multiBalanceRowAsCellBuilders machineFmt opts colspans allCommodities
936986 Value (simpleDateSpanCell $ period_titles_ opts)
937987
938988
0 commit comments