xlsx-0.7.1: test/PivotTableTests.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
module PivotTableTests
( tests
, testPivotTable
, testPivotSrcCells
) where
import Control.Lens
import Data.ByteString.Lazy (ByteString)
import qualified Data.Map as M
import Data.Maybe (mapMaybe)
import qualified Data.Text as T
import Test.Tasty (testGroup, TestTree)
import Test.Tasty.HUnit (testCase)
import Text.RawString.QQ
import Text.XML
import Codec.Xlsx
import Codec.Xlsx.Parser.Internal.PivotTable
import Codec.Xlsx.Types.Internal (unsafeRefId)
import Codec.Xlsx.Types.PivotTable.Internal
import Codec.Xlsx.Writer.Internal.PivotTable
import Diff
tests :: TestTree
tests =
testGroup
"Pivot table tests"
[ testCase "proper pivot table rendering" $ do
let ptFiles = renderPivotTableFiles testPivotSrcCells 3 testPivotTable
parseLBS_ def (pvtfTable ptFiles) @==?
stripContentSpaces (parseLBS_ def testPivotTableDefinition)
parseLBS_ def (pvtfCacheDefinition ptFiles) @==?
stripContentSpaces (parseLBS_ def testPivotCacheDefinition)
, testCase "proper pivot table parsing" $ do
let sheetName = "Sheet1"
ref = CellRef "A1:D5"
forCacheId (CacheId 3) = Just (sheetName, ref, testPivotCacheFields)
forCacheId _ = Nothing
-- fields with numeric values go into cache records
testPivotCacheFields' =
[ if cfName cf == PivotFieldName "Color"
then cf
else cf {cfItems = []}
| cf <- testPivotCacheFields
]
Just (sheetName, ref, testPivotCacheFields', Just (unsafeRefId 1)) @==?
parseCache testPivotCacheDefinition
Just testPivotTable @==?
parsePivotTable forCacheId testPivotTableDefinition
]
testPivotTable :: PivotTable
testPivotTable =
PivotTable
{ _pvtName = "PivotTable1"
, _pvtDataCaption = "Values"
, _pvtLocation = CellRef "A3:D12"
, _pvtSrcRef = CellRef "A1:D5"
, _pvtSrcSheet = "Sheet1"
, _pvtRowFields = [FieldPosition colorField, DataPosition]
, _pvtColumnFields = [FieldPosition yearField]
, _pvtDataFields =
[ DataField
{ _dfName = "Sum of field Price"
, _dfField = priceField
, _dfFunction = ConsolidateSum
}
, DataField
{ _dfName = "Sum of field Count"
, _dfField = countField
, _dfFunction = ConsolidateSum
}
]
, _pvtFields =
[ PivotFieldInfo (Just $ colorField) False FieldSortAscending [CellText "green"]
, PivotFieldInfo (Just $ yearField) True FieldSortManual []
, PivotFieldInfo (Just $ priceField) False FieldSortManual []
, PivotFieldInfo (Just $ countField) False FieldSortManual []
]
, _pvtRowGrandTotals = True
, _pvtColumnGrandTotals = False
, _pvtOutline = False
, _pvtOutlineData = False
}
where
colorField = PivotFieldName "Color"
yearField = PivotFieldName "Year"
priceField = PivotFieldName "Price"
countField = PivotFieldName "Count"
testPivotSrcCells :: CellMap
testPivotSrcCells =
M.fromList $
concat
[ [((row, col), def & cellValue ?~ v) | (col, v) <- zip [1 ..] cells]
| (row, cells) <- zip [1 ..] cellMap
]
where
cellMap =
[ [CellText "Color", CellText "Year", CellText "Price", CellText "Count"]
, [CellText "green", CellDouble 2012, CellDouble 12.23, CellDouble 17]
, [CellText "white", CellDouble 2011, CellDouble 73.99, CellDouble 21]
, [CellText "red", CellDouble 2012, CellDouble 10.19, CellDouble 172]
, [CellText "white", CellDouble 2012, CellDouble 34.99, CellDouble 49]
]
testPivotCacheFields :: [CacheField]
testPivotCacheFields =
[ CacheField
(PivotFieldName "Color")
[CellText "green", CellText "white", CellText "red"]
, CacheField (PivotFieldName "Year") [CellDouble 2012, CellDouble 2011]
, CacheField
(PivotFieldName "Price")
[CellDouble 12.23, CellDouble 73.99, CellDouble 10.19, CellDouble 34.99]
, CacheField
(PivotFieldName "Count")
[CellDouble 17, CellDouble 21, CellDouble 172, CellDouble 49]
]
testPivotTableDefinition :: ByteString
testPivotTableDefinition = [r|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!--Pivot table generated by xlsx-->
<pivotTableDefinition xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" name="PivotTable1" cacheId="3" dataOnRows="1" colGrandTotals="0" dataCaption="Values">
<location ref="A3:D12" firstHeaderRow="1" firstDataRow="2" firstDataCol="1"/>
<pivotFields>
<pivotField name="Color" axis="axisRow" showAll="0" outline="0" sortType="ascending">
<items>
<item h="1" x="0"/><item x="1"/><item x="2"/><item t="default"/>
</items>
</pivotField>
<pivotField name="Year" axis="axisCol" showAll="0" outline="1">
<items>
<item x="0"/><item x="1"/><item t="default"/>
</items>
</pivotField>
<pivotField name="Price" dataField="1" showAll="0" outline="0"/>
<pivotField name="Count" dataField="1" showAll="0" outline="0"/>
</pivotFields>
<rowFields><field x="0"/><field x="-2"/></rowFields>
<colFields><field x="1"/></colFields>
<dataFields>
<dataField name="Sum of field Price" fld="2"/>
<dataField name="Sum of field Count" fld="3"/>
</dataFields>
</pivotTableDefinition>
|]
testPivotCacheDefinition :: ByteString
testPivotCacheDefinition = [r|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><!--Pivot cache definition generated by xlsx-->
<pivotCacheDefinition xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="rId1"
invalid="1" refreshOnLoad="1"
xmlns:ns="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<cacheSource type="worksheet">
<worksheetSource ref="A1:D5" sheet="Sheet1"/>
</cacheSource>
<cacheFields>
<cacheField name="Color">
<sharedItems>
<s v="green"/><s v="white"/><s v="red"/>
</sharedItems>
</cacheField>
<cacheField name="Year">
<sharedItems containsNumber="1" containsString="0" containsSemiMixedTypes="0"/>
</cacheField>
<cacheField name="Price">
<sharedItems containsNumber="1" containsString="0" containsSemiMixedTypes="0"/>
</cacheField>
<cacheField name="Count">
<sharedItems containsNumber="1" containsString="0" containsSemiMixedTypes="0"/>
</cacheField>
</cacheFields>
</pivotCacheDefinition>
|]
stripContentSpaces :: Document -> Document
stripContentSpaces doc@Document {documentRoot = root} =
doc {documentRoot = go root}
where
go e@Element {elementNodes = nodes} =
e {elementNodes = mapMaybe goNode nodes}
goNode (NodeElement el) = Just $ NodeElement (go el)
goNode t@(NodeContent txt) =
if T.strip txt == T.empty
then Nothing
else Just t
goNode other = Just $ other