Permalink
Browse files

reading sheet as a map: fixed skipping empty rows

  • Loading branch information...
1 parent e339cd3 commit 81d78e94c2809347cb2a8775a3ee82cb52274e42 @qrilka committed May 13, 2012
Showing with 64 additions and 28 deletions.
  1. +64 −28 src/Codec/Xlsx/Templater.hs
@@ -9,6 +9,7 @@ module Codec.Xlsx.Templater(
import Codec.Xlsx
import Codec.Xlsx.Parser
import Codec.Xlsx.Writer
+import Control.Applicative ((<$>))
import Data.Conduit
import qualified Data.Conduit.List as CL
import Data.Default (Default (..))
@@ -24,28 +25,41 @@ data TemplateSettings = TemplateSettings { tsOrientation :: Orientation
, tsRepeated :: Int
}
data TemplateValue = TplText Text | TplDouble Double | TplLocalTime LocalTime
+ deriving Show
type TemplateDataRow = M.Map Text TemplateValue
data Converter = Match Text | PassThrough
deriving Show
-data TplCell = TplCell{ converter :: Converter
- , srcCell :: Cell
+data TplCell = TplCell{ tplConverter :: Converter
+ , tplSrc :: Maybe CellData
+ , tplX :: Int
}
deriving Show
-tpl2xlsx :: TemplateValue -> Maybe CellValue
-tpl2xlsx (TplText t) = Just $ CellText t
-tpl2xlsx (TplDouble d) = Just $ CellDouble d
-tpl2xlsx (TplLocalTime t) = Just $ CellLocalTime t
+tpl2xlsx :: TemplateValue -> CellValue
+tpl2xlsx (TplText t) = CellText t
+tpl2xlsx (TplDouble d) = CellDouble d
+tpl2xlsx (TplLocalTime t) = CellLocalTime t
-replacePlaceholders :: [[Cell]] -> TemplateDataRow -> [[Cell]]
-replacePlaceholders d tdr = map (map replace) d
+type TplDataCell = (Int, Int, Maybe CellData)
+
+replacePlaceholders :: Int -> [[TplDataCell]] -> TemplateDataRow -> (Int, [[TplDataCell]])
+replacePlaceholders n d tdr = countMap n (\n -> map $ replace n) d
+ where
+ replace :: Int -> TplDataCell -> TplDataCell
+ replace y (x, _, src@(Just cd@CellData{cdValue=CellText t})) =
+ either (const (x, y, src)) (\ph -> (x, y, Just cd{cdValue=phValue ph})) (getVar t)
+ replace y (x, _, src) = (x, y, src)
+ phValue ph = maybe (CellText ph) tpl2xlsx (M.lookup ph tdr)
+
+countMap :: Int -> (Int -> a -> b) -> [a] -> (Int, [b])
+countMap n f [] = (n, [])
+countMap n f l = (n' + 1, transformed)
where
- replace :: Cell -> Cell
- replace c@Cell{cellValue=Just (CellText t)} = either (const c) (\ph -> c{cellValue=phValue ph}) (getVar t)
- replace c = c
- phValue ph = maybe Nothing tpl2xlsx (M.lookup ph tdr)
+ n' = fst $ last numbered
+ numbered = zip [n..] l
+ transformed = map (uncurry f) numbered -- (\(n, a) -> f n a)
getVar = parse varParser "unnecessary error"
where
@@ -55,30 +69,52 @@ getVar = parse varParser "unnecessary error"
string "}}"
return $ pack name
-buildTemplate :: [Cell] -> [TplCell]
+buildTemplate :: [TplDataCell] -> [TplCell]
buildTemplate = map build
where
- build cell = TplCell{ converter = conv cell
- , srcCell = cell}
- conv cell =
- case cellValue cell of
- Just v@(CellText t) -> either (const $ PassThrough) Match (getVar t)
+ build (x, _, cd) = TplCell{ tplConverter = conv cd
+ , tplSrc = cd
+ , tplX = x}
+ conv cd =
+ case cd of
+ Just CellData{cdValue=CellText t} -> either (const $ PassThrough) Match (getVar t)
Nothing -> PassThrough
-applyTemplate :: [TplCell] -> TemplateDataRow -> [Cell]
-applyTemplate t r = map transform t
+applyTemplate :: [TplCell] -> Int -> TemplateDataRow -> [TplDataCell]
+applyTemplate t y r = map transform t
+ where
+ transform tc = (tplX tc, y,
+ case tplConverter tc of
+ Match k -> fmap (\cd -> cd{cdValue = tpl2xlsx $ fromJust $ M.lookup k r}) (tplSrc tc)
+ PassThrough -> tplSrc tc)
+
+
+map2matrix :: (Maybe ((Int,Int), (Int,Int), M.Map (Int,Int) CellData)) -> [[TplDataCell]]
+map2matrix Nothing = error "invalid template"
+map2matrix (Just ((xmin,xmax), (ymin,ymax), m)) = [[lookupCell x y | x <- [1..xmax]] | y <- [1..ymax]]
+ where
+ lookupCell x y = (x, y, M.lookup (x, y) m)
+
+tplData2Cell :: TplDataCell -> Cell
+tplData2Cell (x, y, cd) =
+ case cd of
+ Nothing ->
+ Cell{cellIx=(col,row), cellStyle=Nothing, cellValue=Nothing}
+ Just CellData{cdValue=v,cdStyle=s} ->
+ Cell{cellIx=(col,row), cellStyle=s, cellValue=Just v}
where
- transform tc =
- case converter tc of
- Match k -> (srcCell tc){cellValue = tpl2xlsx $ fromJust $ M.lookup k r}
- PassThrough -> srcCell tc
+ col = int2col x
+ row = y
runSheet x n (cdr, ts, d) = do
- templateRows <- sheet x n ["A","B","C","D"] $$ CL.consume
+ templateRows <- map2matrix <$> sheetMap x n
let
- (prolog, templateRow : epilog) = splitAt (tsRepeated ts) (templateRows :: [[Cell]])
- tpl = buildTemplate templateRow in
- return (replacePlaceholders prolog cdr ++ map (applyTemplate tpl) d ++ replacePlaceholders epilog cdr)
+ (prolog, templateRow : epilog) = splitAt (tsRepeated ts) templateRows -- :: [[Cell]])
+ tpl = buildTemplate templateRow
+ (n, prolog') = replacePlaceholders 1 prolog cdr
+ (n', d') = countMap n (applyTemplate tpl) d
+ (_, epilog') = replacePlaceholders n' epilog cdr in
+ return $ map (map tplData2Cell) $ concat [prolog', d', epilog']
run :: FilePath -> FilePath -> [(TemplateDataRow, TemplateSettings, [TemplateDataRow])] -> IO ()

0 comments on commit 81d78e9

Please sign in to comment.