@@ -307,7 +307,7 @@ import Hledger.Write.Ods (printFods)
307
307
import Hledger.Write.Html (Html , styledTableHtml , htmlAsLazyText , toHtml )
308
308
import Hledger.Write.Spreadsheet (rawTableContent , headerCell ,
309
309
addHeaderBorders , addRowSpanHeader ,
310
- cellFromMixedAmount , cellsFromMixedAmount )
310
+ cellFromMixedAmount , cellsFromMixedAmount , cellFromAmount )
311
311
import qualified Hledger.Write.Spreadsheet as Ods
312
312
313
313
@@ -593,6 +593,9 @@ renderComponent topaligned oneline opts (acctname, dep, total) (FormatField ljus
593
593
}
594
594
595
595
596
+ headerWithoutBorders :: [Ods. Cell () text ] -> [Ods. Cell Ods. NumLines text ]
597
+ headerWithoutBorders = map (\ c -> c {Ods. cellBorder = Ods. noBorder})
598
+
596
599
simpleDateSpanCell :: DateSpan -> Ods. Cell Ods. NumLines Text
597
600
simpleDateSpanCell = Ods. defaultCell . showDateSpan
598
601
@@ -621,8 +624,11 @@ balanceReportAsSpreadsheet opts (items, total) =
621
624
headers =
622
625
addHeaderBorders $ map headerCell $
623
626
" account" : case layout_ opts of
627
+ LayoutBareWide -> allCommodities
624
628
LayoutBare -> [" commodity" , " balance" ]
625
629
_ -> [" balance" ]
630
+ allCommodities =
631
+ S. toAscList $ foldMap (\ (_,_,_,ma) -> maCommodities ma) items
626
632
rows ::
627
633
RowClass -> BalanceReportItem ->
628
634
[[Ods. Cell Ods. NumLines Text ]]
@@ -634,6 +640,15 @@ balanceReportAsSpreadsheet opts (items, total) =
634
640
cell $ renderBalanceAcct opts nbsp (name, dispName, dep) in
635
641
addRowSpanHeader accountCell $
636
642
case layout_ opts of
643
+ LayoutBareWide ->
644
+ let bopts =
645
+ machineFmt {
646
+ displayCommodity = False ,
647
+ displayCommodityOrder = Just allCommodities
648
+ } in
649
+ [map (\ bldAmt ->
650
+ fmap wbToText $ cellFromAmount bopts (amountClass rc, bldAmt)) $
651
+ showMixedAmountLinesPartsB bopts ma]
637
652
LayoutBare ->
638
653
map (\ a -> [cell $ acommodity a, renderAmount rc $ mixedAmount a])
639
654
. amounts $ mixedAmountStripCosts ma
@@ -657,29 +672,41 @@ balanceReportAsSpreadsheet opts (items, total) =
657
672
multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV
658
673
multiBalanceReportAsCsv opts@ ReportOpts {.. } report =
659
674
(if transpose_ then transpose else id ) $
660
- rawTableContent $ header : body ++ totals
675
+ rawTableContent $ header ++ body ++ totals
661
676
where
662
677
(header, body, totals) =
663
- multiBalanceReportAsSpreadsheetParts machineFmt opts report
678
+ multiBalanceReportAsSpreadsheetParts machineFmt opts
679
+ (allCommoditiesFromPeriodicReport $ prRows report) report
664
680
665
681
-- | Render the Spreadsheet table rows (CSV, ODS, HTML) for a MultiBalanceReport.
666
682
-- Returns the heading row, 0 or more body rows, and the totals row if enabled.
667
683
multiBalanceReportAsSpreadsheetParts ::
668
- AmountFormat -> ReportOpts -> MultiBalanceReport ->
669
- ([Ods. Cell Ods. NumLines Text ],
684
+ AmountFormat -> ReportOpts ->
685
+ [CommoditySymbol ] -> MultiBalanceReport ->
686
+ ([[Ods. Cell Ods. NumLines Text ]],
670
687
[[Ods. Cell Ods. NumLines Text ]],
671
688
[[Ods. Cell Ods. NumLines Text ]])
672
- multiBalanceReportAsSpreadsheetParts fmt opts@ ReportOpts {.. } (PeriodicReport colspans items tr) =
673
- (headers, concatMap fullRowAsTexts items, addTotalBorders totalrows)
689
+ multiBalanceReportAsSpreadsheetParts fmt opts@ ReportOpts {.. }
690
+ allCommodities (PeriodicReport colspans items tr) =
691
+ (allHeaders, concatMap fullRowAsTexts items, addTotalBorders totalrows)
674
692
where
675
693
accountCell label =
676
694
(Ods. defaultCell label) {Ods. cellClass = Ods. Class " account" }
677
695
hCell cls label = (headerCell label) {Ods. cellClass = Ods. Class cls}
696
+ allHeaders =
697
+ case layout_ of
698
+ LayoutBareWide ->
699
+ [headerWithoutBorders $
700
+ Ods. emptyCell :
701
+ concatMap (Ods. horizontalSpan allCommodities) dateHeaders,
702
+ headers]
703
+ _ -> [headers]
678
704
headers =
679
705
addHeaderBorders $
680
706
hCell " account" " account" :
681
707
case layout_ of
682
708
LayoutTidy -> map headerCell tidyColumnLabels
709
+ LayoutBareWide -> dateHeaders >> map headerCell allCommodities
683
710
LayoutBare -> headerCell " commodity" : dateHeaders
684
711
_ -> dateHeaders
685
712
dateHeaders =
@@ -700,7 +727,7 @@ multiBalanceReportAsSpreadsheetParts fmt opts@ReportOpts{..} (PeriodicReport col
700
727
rowAsText Total simpleDateSpanCell tr
701
728
rowAsText rc dsCell =
702
729
map (map (fmap wbToText)) .
703
- multiBalanceRowAsCellBuilders fmt opts colspans rc dsCell
730
+ multiBalanceRowAsCellBuilders fmt opts colspans allCommodities rc dsCell
704
731
705
732
tidyColumnLabels :: [Text ]
706
733
tidyColumnLabels =
@@ -720,10 +747,12 @@ multiBalanceReportAsSpreadsheet ::
720
747
((Int , Int ), [[Ods. Cell Ods. NumLines Text ]])
721
748
multiBalanceReportAsSpreadsheet ropts mbr =
722
749
let (header,body,total) =
723
- multiBalanceReportAsSpreadsheetParts oneLineNoCostFmt ropts mbr
750
+ multiBalanceReportAsSpreadsheetParts oneLineNoCostFmt ropts
751
+ (allCommoditiesFromPeriodicReport $ prRows mbr) mbr
724
752
in (if transpose_ ropts then swap *** Ods. transpose else id ) $
725
- ((1 , case layout_ ropts of LayoutWide _ -> 1 ; _ -> 0 ),
726
- header : body ++ total)
753
+ ((case layout_ ropts of LayoutBareWide -> 2 ; _ -> 1 ,
754
+ case layout_ ropts of LayoutWide _ -> 1 ; _ -> 0 ),
755
+ header ++ body ++ total)
727
756
728
757
729
758
-- | Render a multi-column balance report as plain text suitable for console output.
@@ -794,19 +823,24 @@ multiBalanceReportAsTable opts@ReportOpts{summary_only_, average_, balanceaccum_
794
823
(concat rows)
795
824
where
796
825
colheadings = [" Commodity" | layout_ opts == LayoutBare ]
797
- ++ (if not summary_only_ then map (reportPeriodName balanceaccum_ spans) spans else [] )
826
+ ++ (if not summary_only_
827
+ then case layout_ opts of
828
+ LayoutBareWide -> spans >> allCommodities
829
+ _ -> map (reportPeriodName balanceaccum_ spans) spans
830
+ else [] )
798
831
++ [" Total" | multiBalanceHasTotalsColumn opts]
799
832
++ [" Average" | average_]
833
+ allCommodities = allCommoditiesFromPeriodicReport items
800
834
(accts, rows) = unzip $ fmap fullRowAsTexts items
801
835
where
802
836
fullRowAsTexts row = (replicate (length rs) (renderacct row), rs)
803
837
where
804
- rs = multiBalanceRowAsText opts row
838
+ rs = multiBalanceRowAsText opts allCommodities row
805
839
renderacct row' = T. replicate (prrIndent row' * 2 ) " " <> prrDisplayName row'
806
840
addtotalrow
807
841
| no_total_ opts = id
808
842
| otherwise =
809
- let totalrows = multiBalanceRowAsText opts tr
843
+ let totalrows = multiBalanceRowAsText opts allCommodities tr
810
844
rowhdrs = Group NoLine $ map Header $ totalRowHeadingText : replicate (length totalrows - 1 ) " "
811
845
colhdrs = Header [] -- unused, concatTables will discard
812
846
in (flip (concatTables SingleLine ) $ Table rowhdrs colhdrs totalrows)
@@ -815,12 +849,17 @@ multiBalanceReportAsTable opts@ReportOpts{summary_only_, average_, balanceaccum_
815
849
multiColumnTableInterRowBorder = NoLine
816
850
multiColumnTableInterColumnBorder = if pretty_ opts then SingleLine else NoLine
817
851
852
+ allCommoditiesFromPeriodicReport ::
853
+ [PeriodicReportRow a MixedAmount ] -> [CommoditySymbol ]
854
+ allCommoditiesFromPeriodicReport =
855
+ S. toAscList . foldMap (foldMap maCommodities . prrAmounts)
856
+
818
857
multiBalanceRowAsCellBuilders ::
819
- AmountFormat -> ReportOpts -> [DateSpan ] ->
858
+ AmountFormat -> ReportOpts -> [DateSpan ] -> [ CommoditySymbol ] ->
820
859
RowClass -> (DateSpan -> Ods. Cell Ods. NumLines Text ) ->
821
860
PeriodicReportRow a MixedAmount ->
822
861
[[Ods. Cell Ods. NumLines WideBuilder ]]
823
- multiBalanceRowAsCellBuilders bopts ropts@ ReportOpts {.. } colspans
862
+ multiBalanceRowAsCellBuilders bopts ropts@ ReportOpts {.. } colspans allCommodities
824
863
rc renderDateSpanCell (PeriodicReportRow _acct as rowtot rowavg) =
825
864
case layout_ of
826
865
LayoutWide width -> [fmap (cellFromMixedAmount bopts{displayMaxWidth= width}) clsamts]
@@ -831,6 +870,8 @@ multiBalanceRowAsCellBuilders bopts ropts@ReportOpts{..} colspans
831
870
. transpose -- each row becomes a list of Text quantities
832
871
. map (cellsFromMixedAmount bopts{displayCommodity= False , displayCommodityOrder= Just cs, displayMinWidth= Nothing })
833
872
$ clsamts
873
+ LayoutBareWide -> [concatMap (cellsFromMixedAmount bopts{displayCommodity= False , displayCommodityOrder= Just allCommodities, displayMinWidth= Nothing })
874
+ $ clsamts]
834
875
LayoutTidy -> concat
835
876
. zipWith (map . addDateColumns) colspans
836
877
. map ( zipWith (\ c a -> [wbCell c, a]) cs
@@ -873,16 +914,20 @@ multiBalanceHasTotalsColumn :: ReportOpts -> Bool
873
914
multiBalanceHasTotalsColumn ropts =
874
915
row_total_ ropts && balanceaccum_ ropts `notElem` [Cumulative , Historical ]
875
916
876
- multiBalanceRowAsText :: ReportOpts -> PeriodicReportRow a MixedAmount -> [[WideBuilder ]]
877
- multiBalanceRowAsText opts =
917
+ multiBalanceRowAsText ::
918
+ ReportOpts -> [CommoditySymbol ] -> PeriodicReportRow a MixedAmount -> [[WideBuilder ]]
919
+ multiBalanceRowAsText opts allCommodities =
878
920
rawTableContent .
879
- multiBalanceRowAsCellBuilders oneLineNoCostFmt{displayColour= color_ opts} opts []
921
+ multiBalanceRowAsCellBuilders oneLineNoCostFmt{displayColour= color_ opts}
922
+ opts [] allCommodities
880
923
Value simpleDateSpanCell
881
924
882
- multiBalanceRowAsCsvText :: ReportOpts -> [DateSpan ] -> PeriodicReportRow a MixedAmount -> [[T. Text ]]
883
- multiBalanceRowAsCsvText opts colspans =
925
+ multiBalanceRowAsCsvText ::
926
+ ReportOpts -> [DateSpan ] -> [CommoditySymbol ] ->
927
+ PeriodicReportRow a MixedAmount -> [[T. Text ]]
928
+ multiBalanceRowAsCsvText opts colspans allCommodities =
884
929
map (map (wbToText . Ods. cellContent)) .
885
- multiBalanceRowAsCellBuilders machineFmt opts colspans
930
+ multiBalanceRowAsCellBuilders machineFmt opts colspans allCommodities
886
931
Value simpleDateSpanCell
887
932
888
933
0 commit comments