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