module Codec.Xlsx.Types.Internal.SharedStringTable (
SharedStringTable(..)
, sstConstruct
, sstLookupText
, sstLookupRich
, sstItem
) where
import Control.Monad
import Data.Maybe (mapMaybe)
import Data.Text (Text)
import Data.Vector (Vector)
import Numeric.Search.Range (searchFromTo)
import Text.XML
import Text.XML.Cursor
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.Vector as V
import Codec.Xlsx.Parser.Internal
import Codec.Xlsx.Types
import Codec.Xlsx.Writer.Internal
newtype SharedStringTable = SharedStringTable {
sstTable :: Vector XlsxText
}
deriving (Show, Eq, Ord)
instance ToDocument SharedStringTable where
toDocument = documentFromElement "Shared string table generated by xlsx"
. toElement "sst"
instance ToElement SharedStringTable where
toElement nm SharedStringTable{..} = Element {
elementName = nm
, elementAttributes = Map.empty
, elementNodes = map (NodeElement . toElement "si")
$ V.toList sstTable
}
instance FromCursor SharedStringTable where
fromCursor cur = do
let
items = cur $/ element (n"si") >=> fromCursor
return (SharedStringTable (V.fromList items))
sstConstruct :: [Worksheet] -> SharedStringTable
sstConstruct =
SharedStringTable . V.fromList . uniq . concatMap goSheet
where
goSheet :: Worksheet -> [XlsxText]
goSheet = mapMaybe (_cellValue >=> sstEntry) . Map.elems . _wsCells
sstEntry :: CellValue -> Maybe XlsxText
sstEntry (CellText text) = Just $ XlsxText text
sstEntry (CellRich rich) = Just $ XlsxRichText rich
sstEntry _ = Nothing
uniq :: Ord a => [a] -> [a]
uniq = Set.elems . Set.fromList
sstLookupText :: SharedStringTable -> Text -> Int
sstLookupText sst = sstLookup sst . XlsxText
sstLookupRich :: SharedStringTable -> [RichTextRun] -> Int
sstLookupRich sst = sstLookup sst . XlsxRichText
sstLookup :: SharedStringTable -> XlsxText -> Int
sstLookup SharedStringTable{sstTable = shared} si =
case searchFromTo (\p -> shared V.! p >= si) 0 (V.length shared 1) of
Just i -> i
Nothing -> error $ "SST entry for " ++ show si ++ " not found"
sstItem :: SharedStringTable -> Int -> XlsxText
sstItem (SharedStringTable shared) = (V.!) shared