From 8b4a99c4d5a950fba2385c14d6339a76f6b081ca Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Sun, 18 Nov 2012 18:21:52 +0000 Subject: [PATCH] 79: convert: add a skip-lines directive (Magnus Henoch) --- MANUAL.md | 7 +++++++ hledger-lib/Hledger/Data/Types.hs | 3 ++- hledger-lib/Hledger/Read/CsvReader.hs | 16 +++++++++++++--- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/MANUAL.md b/MANUAL.md index cbc1d277e..ad73f6ee5 100644 --- a/MANUAL.md +++ b/MANUAL.md @@ -517,11 +517,13 @@ file with `--rules-file` (useful when reading from standard input). An example - sample.csv: sample.csv: + "Date","Note","Amount" "2012/3/22","TRANSFER TO SAVINGS","-10.00" "2012/3/23","SOMETHING ELSE","5.50" sample.rules: + skip-lines 1 date-field 0 description-field 1 amount-field 2 @@ -632,6 +634,11 @@ results.) > Which field contains the transaction cleared status (`*`). +`skip-lines` + +> How many lines to skip in the beginning of the file, e.g. to skip a +> line of column headings. + Account-assigning rules select an account to transfer to based on the description field (unless `account2-field` is used.) Each account-assigning rule is a paragraph consisting of one or more diff --git a/hledger-lib/Hledger/Data/Types.hs b/hledger-lib/Hledger/Data/Types.hs index e6f2ab67b..8da0afed9 100644 --- a/hledger-lib/Hledger/Data/Types.hs +++ b/hledger-lib/Hledger/Data/Types.hs @@ -203,7 +203,8 @@ data CsvRules = CsvRules { account2Field :: Maybe FieldPosition, effectiveDateField :: Maybe FieldPosition, baseAccount :: AccountName, - accountRules :: [AccountRule] + accountRules :: [AccountRule], + skipLines :: Int } deriving (Show, Eq) type FieldPosition = Int diff --git a/hledger-lib/Hledger/Read/CsvReader.hs b/hledger-lib/Hledger/Read/CsvReader.hs index 676836865..3757cc9d4 100644 --- a/hledger-lib/Hledger/Read/CsvReader.hs +++ b/hledger-lib/Hledger/Read/CsvReader.hs @@ -98,7 +98,8 @@ nullrules = CsvRules { account2Field=Nothing, effectiveDateField=Nothing, baseAccount="unknown", - accountRules=[] + accountRules=[], + skipLines=0 } type CsvRecord = [String] @@ -137,9 +138,10 @@ readJournalFromCsv mrulesfile csvfile csvdata = rules <- liftM (either (throw.userError.show) id) $ parseCsvRulesFile rulesfile let requiredfields = (maxFieldIndex rules + 1) - badrecords = take 1 $ filter ((< requiredfields).length) records + realrecords = drop (skipLines rules) records + badrecords = take 1 $ filter ((< requiredfields).length) realrecords return $ case badrecords of - [] -> Right nulljournal{jtxns=sortBy (comparing tdate) $ map (transactionFromCsvRecord rules) records} + [] -> Right nulljournal{jtxns=sortBy (comparing tdate) $ map (transactionFromCsvRecord rules) realrecords} (_:_) -> Left $ "Parse error: at least one CSV record does not contain a field referenced by the conversion rules file:\n"++(show $ head badrecords) -- | Ensure there is a conversion rules file at the given path, creating a @@ -189,6 +191,7 @@ newRulesFileContent = let prognameandversion = "hledger" in "# Add rules to this file for more accurate conversion, see\n"++ "# http://hledger.org/MANUAL.html#convert\n" ++ "\n" ++ + "skip-lines 0\n" ++ "base-account assets:bank:checking\n" ++ "date-field 0\n" ++ "description-field 4\n" ++ @@ -251,6 +254,7 @@ definitions = do ,effectivedatefield ,basecurrency ,baseaccount + ,skiplines ,commentline ] "definition" return () @@ -350,6 +354,12 @@ baseaccount = do optional newline updateState (\r -> r{baseAccount=v}) +skiplines = do + string "skip-lines" + many1 spacenonewline + v <- restofline + updateState (\r -> r{skipLines=read v}) + accountrule :: GenParser Char CsvRules AccountRule accountrule = do many blankorcommentline