packages feed

xlsx-tabular 0.1.0.2 → 0.1.1

raw patch · 2 files changed

+89/−39 lines, 2 filesdep ~xlsx

Dependency ranges changed: xlsx

Files

src/Codec/Xlsx/Util/Tabular.hs view
@@ -1,7 +1,35 @@ {-# LANGUAGE FlexibleContexts  #-} {-# LANGUAGE LambdaCase        #-} {-# LANGUAGE OverloadedStrings #-}--- | Convinience utility to read Xlsx tabular cells.++{- | Convenience utility to read Xlsx tabular cells.++The majority of the @toTableRows*@ functions assume that the table+of interest consiste of contiguous rows styled with borders lines+surrounding all cells, with possible text above and below the table+that is not of interest. Like so:++@+Some documentation here....+---------------------------+| Header1 | Header2 | ... |+---------------------------+| Value1  | Value2  | ... |+---------------------------+| Value1  | Value2  | ... |+---------------------------+Maybe some annoying text here, I don't care about.+@++The heauristic used for table row selection in these functions is+that any table rows will have a bottom border line.++If the above heuristic is not valid for your table you can instead+provide your own row selection predicate to the `toTableRowsCustom`+function. For example, the predicate @\\_ _ -> True@ (or @(const+. const) True@) will select all contiguous rows.++-} module Codec.Xlsx.Util.Tabular        (          -- * Types@@ -24,13 +52,18 @@        , toTableRowsFromFile        , toTableRows        , toTableRows'+         -- * Custom row predicates+       , toTableRowsCustom        ) where  import Codec.Xlsx.Util.Tabular.Imports import qualified Data.ByteString.Lazy as ByteString +type Row =+  (Int, Cols)+ type Rows =-  [(Int, Cols)]+  [(Int, Cols)] -- [Row]  type Cols =   [(Int, Cell)]@@ -38,8 +71,16 @@ type RowValues =   [(Int, [(Int, Maybe CellValue)])] +-- | A @RowPredicate@ is given the Xlsx "StyleSheet" as well as the+-- row itself (consisting of the row's index and the row's cells) and+-- should return @True@ if the row is part of the table and false+-- otherwise.+type RowPredicate =+  StyleSheet -> Row -> Bool --- |Read from Xlsx file as tabular rows+-- |Read tabular rows from the first sheel of an Xlsx file.+-- The table is assumed to consist of all contiguous rows+-- that have bottom border lines, starting with the header. toTableRowsFromFile :: Int -- ^ Starting row index (header row)                     -> String -- ^ File name                     -> IO (Maybe Tabular)@@ -50,38 +91,51 @@   pure rows  -- |Decode cells as tabular rows.+-- The table is assumed to consist of all contiguous rows+-- that have bottom border lines, starting with the header. toTableRows :: Xlsx -- ^ Xlsx Workbook             -> Text -- ^ Worksheet name to decode             -> Int -- ^ Starting row index (header row)             -> Maybe Tabular-toTableRows xlsx sheetName offset =-  decodeRows <$> styles <*> Just offset <*> rows-  where-    styles = parseStyleSheet (xlsx ^. xlStyles) ^? _Right-    rows =-      xlsx-      ^? ixSheet sheetName-      . wsCells-      . to toRows+toTableRows = toTableRowsCustom borderBottomPredicate --- |Decode cells as tabular rows from first sheet.+-- |Decode cells from first sheet as tabular rows.+-- The table is assumed to consist of all contiguous rows+-- that have bottom border lines, starting with the header. toTableRows' :: Xlsx -- ^ Xlsx Workbook              -> Int -- ^ Starting row index (header row)              -> Maybe Tabular toTableRows' xlsx offset =   toTableRows xlsx firstSheetName offset   where-    firstSheetName =-      xlsx ^. xlSheets-      & head-      & fst+    firstSheetName = fst $ head $ xlsx ^. xlSheets+    -- ^ TODO: Is this still true with xlsx-0.3 or are sheets now+    -- in alphabetical order?? -decodeRows ss offset rs =+-- | Decode cells as tabular rows.+--   The table is assumed to consist of all contiguous rows+--   that fulfill the given predicate, starting with the header.+--+--   The predicate function is given the Xlsx @StyleSheet@ as well+--   as a row (consisting of the row's index and the row's cells)+--   and should return @True@ if the row is part of the table.+toTableRowsCustom :: (StyleSheet -> (Int, [(Int, Cell)]) -> Bool)+                           -- ^ Predicate for row selection+                  -> Xlsx  -- ^ Xlsx Workbook+                  -> Text  -- ^ Worksheet name to decode+                  -> Int   -- ^ Starting row index (header row)+                  -> Maybe Tabular+toTableRowsCustom predicate xlsx sheetName offset = do+  styles <- parseStyleSheet (xlsx ^. xlStyles) ^? _Right+  rows   <- xlsx ^? ixSheet sheetName . wsCells . to toRows+  decodeRows (predicate styles) offset rows++decodeRows p offset rs = if null rs' then Nothing else Just $   def   & tabularHeads .~ header'   & tabularRows .~ rows   where-    rs' = getCells ss offset rs+    rs' = getCells p offset rs     header = head rs' ^. _2     header' =       header@@ -103,15 +157,15 @@         f (i, cell) =           [cell | cix ^. contains i] --- |行から値のあるセルを取り出す-getCells :: StyleSheet -- ^スタイルシート-         -> Int -- ^開始行-         -> Rows -- ^セル行+-- |Pickup cells that has value from line+getCells :: (Row -> Bool) -- ^ Predicate+         -> Int -- ^ Start line number+         -> Rows -- ^ cell rows          -> RowValues-getCells ss i rs =-  startAt ss i rs+getCells p i rs =+  startAt i rs   & takeContiguous i-  & takeUntil ss+  & takeWhile p   & fmap rvs   & filter vs   where@@ -122,26 +176,22 @@     vs (i, cs) =       any (\(_, v) -> isJust v) cs -startAt :: StyleSheet -> Int -> Rows -> Rows-startAt ss i rs =+startAt :: Int -> Rows -> Rows+startAt i rs =   dropWhile f rs   where     f (x, _) =       x < i --- |指定の行から連続している行を取り出す+-- |Take contiguous rows that start from i takeContiguous :: Int -> Rows -> Rows takeContiguous i rs =   [r | (x, r@(y, _)) <- zip [i..] rs, x == y] --- |有効セルのすべてに枠線(Bottom側)が存在しなくなる--- |すなわち枠囲みの欄外になるまでの行を取り出す-takeUntil :: StyleSheet -> Rows -> Rows-takeUntil ss rs =-  takeWhile f rs-  where-    f (i, cs) =-      or $ rowBordersHas borderBottom ss cs+-- |Take rows while all valued cell has bottom border line.+-- |  * no bottom border line means out of table.+borderBottomPredicate :: RowPredicate -- StyleSheet -> Row -> Bool+borderBottomPredicate ss = or . rowBordersHas borderBottom ss . snd  rowBordersHas v ss cs =   x
xlsx-tabular.cabal view
@@ -1,5 +1,5 @@ name:                xlsx-tabular-version:             0.1.0.2+version:             0.1.1 synopsis:            Xlsx table decode utility description:         Please see README.md homepage:            http://github.com/kkazuo/xlsx-tabular#readme@@ -26,7 +26,7 @@                      , data-default                      , lens                      , text-                     , xlsx+                     , xlsx >= 0.3   default-language:    Haskell2010  test-suite xlsx-tabular-test