Skip to content

Instantly share code, notes, and snippets.

@schoettl
Created September 20, 2021 08:18
Show Gist options
  • Save schoettl/1c8cfbc49ac573a34db5ef349a5f52a1 to your computer and use it in GitHub Desktop.
Save schoettl/1c8cfbc49ac573a34db5ef349a5f52a1 to your computer and use it in GitHub Desktop.
Xentral Adressen Export umwandeln in 3CX Adressbuch Import-Format
#!/usr/bin/env stack
{- stack script
--resolver lts-18.10
--package "cassava text vector bytestring text-regex-replace"
-}
-- Download Adresses from Xentral into CSV file from
-- https://xxx.xentral.biz/index.php?module=exportvorlage&action=list
-- Then run:
-- ./csv-to-xxx < ~/Downloads/export.csv
-- Exportvorlage muss diese Felder in dieser Reihenfloge exportieren:
-- useredittimestamp; ansprechpartner; name; firma; mobil; telefon; email; telefax; geloescht;
-- CSV muss ,-getrennt sein, "-gequoted sein und Spaltenüberschriften beinhalten.
{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
import Data.Csv
import Control.Applicative
import qualified Data.Vector as V
import Data.Char
import Data.Text (isPrefixOf, Text, strip)
import qualified Data.Text as T
import qualified Data.ByteString.Lazy as BS
import qualified Data.ByteString.Lazy.Char8 as BSC8
import GHC.Generics (Generic)
import Text.Printf
import Data.List (sortOn)
import Data.Maybe (catMaybes, mapMaybe)
import Data.Text.ICU.Replace (replaceAll)
opts = defaultDecodeOptions {decDelimiter = fromIntegral (ord ',')}
data Item = Item
{ ieditts :: Text
, iansprechp :: Text
, iname :: Text
, ifirma :: Text
, imobil :: Text
, itelefon :: Text
, iemail :: Text
, itelefax :: Text
, isystemid :: Text
, igeloescht :: Text
, iunused :: Text
} deriving (Show, Generic)
instance FromRecord Item
main :: IO ()
main = do
s <- BS.getContents
case decodeWith opts HasHeader s :: Either String (V.Vector Item) of
Left s -> putStrLn s
Right as -> do
let as' = take 100000 $ reverse $ sortOn ieditts $ Prelude.filter (\i -> igeloescht i /= "1") $ map trimItem $ V.toList as
let headers = ["FirstΝame", "LastΝame", "Company", "Mobile", "Home", "Business", "Email", "BusinessFax"]
let res = headers : mapMaybe printItem as'
BSC8.putStrLn $ encodeWith defaultEncodeOptions res
printItem :: Item -> Maybe [Text]
printItem i
| imobil i /= "" || itelefon i /= ""
= Just
[ fst $ firstLast i
, snd $ firstLast i
, iname i
, imobil i
, ""::Text
, itelefon i
, iemail i
, itelefax i
]
| otherwise = Nothing
firstLast :: Item -> (Text, Text)
firstLast Item{iname=n,iansprechp=a,ifirma=f}
| n == "" = let as = T.words a in if length as > 1
then (head as, T.unwords $ tail as)
else ("", a)
| otherwise = let ns = T.words n in if length ns > 1
then (head ns, T.unwords $ tail ns)
else ("", n)
trimItem :: Item -> Item
trimItem (Item a b c d e f g h i j k) = Item (strip a) (strip b) (strip c) (strip d) (fixPhoneNumbers $ strip e) (fixPhoneNumbers $ strip f) (strip g) (fixPhoneNumbers $ strip h) (strip i) (strip j) (strip k)
fixPhoneNumbers :: Text -> Text
fixPhoneNumbers = replaceAll "[^0-9+-]" ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment