module Codec.Xlsx.Parser.Internal.PivotTable (
parsePivotTable
, parseCache
) where
import Control.Applicative
import Data.ByteString.Lazy (ByteString)
import Data.Maybe (listToMaybe, maybeToList)
import Data.Text (Text)
import Text.XML
import Text.XML.Cursor
import Codec.Xlsx.Parser.Internal
import Codec.Xlsx.Types.Common
import Codec.Xlsx.Types.PivotTable
import Codec.Xlsx.Types.PivotTable.Internal
parsePivotTable
:: (CacheId -> Maybe (Text, Range, [PivotFieldName]))
-> ByteString
-> Maybe PivotTable
parsePivotTable srcByCacheId bs =
listToMaybe . parse . fromDocument $ parseLBS_ def bs
where
parse cur = do
cacheId <- fromAttribute "cacheId" cur
case srcByCacheId cacheId of
Nothing -> fail "no such cache"
Just (_pvtSrcSheet, _pvtSrcRef, fieldNames) -> do
_pvtDataCaption <- attribute "dataCaption" cur
_pvtName <- attribute "name" cur
_pvtLocation <- cur $/ element (n_ "location") >=> fromAttribute "ref"
_pvtRowGrandTotals <- fromAttributeDef "rowGrandTotals" True cur
_pvtColumnGrandTotals <- fromAttributeDef "colGrandTotals" True cur
_pvtOutline <- fromAttributeDef "outline" False cur
_pvtOutlineData <- fromAttributeDef "outlineData" False cur
let nToField = zip [0 ..] fieldNames
outlines =
cur $/ element (n_ "pivotFields") &/ element (n_ "pivotField") >=>
fromAttributeDef "outline" True
_pvtFields =
[ PivotFieldInfo {_pfiName = name, _pfiOutline = outline}
| (name, outline) <- zip fieldNames outlines
]
_pvtRowFields =
cur $/ element (n_ "rowFields") &/ element (n_ "field") >=>
fromAttribute "x" >=> fieldPosition
_pvtColumnFields =
cur $/ element (n_ "colFields") &/ element (n_ "field") >=>
fromAttribute "x" >=> fieldPosition
_pvtDataFields =
cur $/ element (n_ "dataFields") &/ element (n_ "dataField") >=> \c -> do
fld <- fromAttribute "fld" c
_dfField <- maybeToList $ lookup fld nToField
_dfName <- fromAttributeDef "name" "" c
_dfFunction <- fromAttributeDef "subtotal" ConsolidateSum c
return DataField {..}
fieldPosition :: Int -> [PositionedField]
fieldPosition (2) = return DataPosition
fieldPosition n =
FieldPosition <$> maybeToList (lookup n nToField)
return PivotTable {..}
parseCache :: ByteString -> Maybe (Text, CellRef, [PivotFieldName])
parseCache bs = listToMaybe . parse . fromDocument $ parseLBS_ def bs
where
parse cur = do
(sheet, ref) <-
cur $/ element (n_ "cacheSource") &/ element (n_ "worksheetSource") >=>
liftA2 (,) <$> attribute "sheet" <*> fromAttribute "ref"
let fieldNames =
cur $/ element (n_ "cacheFields") &/ element (n_ "cacheField") >=>
fromAttribute "name"
return (sheet, ref, fieldNames)