diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2013, Mark Baran
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Mark Baran nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/hs-excelx.cabal b/hs-excelx.cabal
new file mode 100644
--- /dev/null
+++ b/hs-excelx.cabal
@@ -0,0 +1,22 @@
+-- Initial hs-excel.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                hs-excelx
+version:             0.5.0.0
+synopsis:            HS-Excelx provides basic read-only access to Excel 2007 and 2010 documents in XLSX format.
+-- description:         
+license:             BSD3
+license-file:        LICENSE
+author:              Mark Baran
+maintainer:          mebaran@gmail.com
+-- copyright:           
+category:            Data
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules:     Data.Excelx
+  -- other-modules:       
+  build-depends:       base ==4.5.*, containers ==0.4.*, time ==1.4.*, mtl ==2.1.*, 
+                       text ==0.11.*, bytestring ==0.9.*, zip-archive ==0.1.*, xml-conduit ==1.0.*
+  hs-source-dirs:      src
diff --git a/src/Data/Excelx.hs b/src/Data/Excelx.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Excelx.hs
@@ -0,0 +1,211 @@
+{-# LANGUAGE QuasiQuotes, OverloadedStrings, FlexibleContexts, FlexibleInstances #-}
+
+module Data.Excelx(openExcelx, toExcelx,
+                   sheet, cell, row, rows, column,
+                   fromCell) where
+
+import Data.Maybe
+import Data.Monoid
+
+import Data.Time.LocalTime
+import Data.Time.Calendar
+
+import Control.Monad
+import Control.Monad.Reader
+
+import qualified Data.Text as T
+import qualified Data.ByteString.Lazy as BS 
+import Codec.Archive.Zip
+
+import Text.XML as XML
+import Text.XML.Cursor 
+
+type Formula = T.Text
+data Position = R1C1 Int Int | A1 T.Text deriving Show
+data Cell = NumericCell Position Double
+          | TextCell Position T.Text
+          | FormulaCell Position Formula Cell
+          | BlankCell Position 
+          | NoCell Position deriving Show
+
+valueCell :: Cell -> Cell
+valueCell (FormulaCell _ _ valuecell) = valuecell
+valueCell valuecell = valuecell
+
+class FromCell a where
+    fromCell :: Cell -> a
+
+instance FromCell Double where
+    fromCell c = case valueCell c of
+                   NumericCell _ d -> d
+                   _ -> 0.0
+
+instance FromCell Integer where
+    fromCell c = floor (fromCell c :: Double)
+
+instance FromCell T.Text where
+    fromCell c = case valueCell c of
+                   TextCell _ t -> t
+                   NumericCell _ t -> T.pack $ show t
+                   _ -> ""
+
+instance FromCell String where
+    fromCell c = T.unpack $ fromCell c
+
+instance FromCell Day where
+    fromCell c = addDays (fromCell c) (fromGregorian 1899 12 30)
+
+instance FromCell TimeOfDay where
+    fromCell c = dayFractionToTimeOfDay part
+        where
+          d = fromCell c :: Double
+          part = toRational $ d - (fromInteger $ floor d)
+
+instance FromCell LocalTime where
+    fromCell c = LocalTime (fromCell c) (fromCell c)
+
+instance FromCell a => FromCell (Maybe a) where
+    fromCell c = case valueCell c of
+                   BlankCell _ -> Nothing
+                   NoCell _ -> Nothing
+                   _ -> Just (fromCell c)
+
+instance FromCell a => FromCell (Either Position a) where
+    fromCell c = case valueCell c of
+                   NoCell pos -> Left pos
+                   _ -> Right $ fromCell c
+
+catCells :: [Cell] -> [Cell]
+catCells cells = filter noCell cells
+    where noCell c = case c of
+              NoCell _ -> True
+              _ -> False
+
+a1form :: Position -> T.Text
+a1form (A1 t) = t
+a1form (R1C1 i j) = T.toUpper . T.pack $ alpha (max j 1) ++ show (max i 1)
+  where 
+    alphabet = map reverse [c : s | s <- "" : alphabet, c <- ['a' .. 'z']]
+    alpha idx = alphabet !! (idx - 1)
+
+type SharedStringIndex = [T.Text]
+type SheetIndex = [(T.Text, FilePath)]
+data Excelx = Excelx {archive :: Archive, sharedStrings :: SharedStringIndex, sheetIndex :: SheetIndex}
+          
+findXMLEntry :: FilePath -> Archive -> Maybe Cursor
+findXMLEntry path ar = do
+  entry <- findEntryByPath path ar
+  case parseLBS def (fromEntry entry) of
+    Left _ -> fail $ "Invalid entry: " ++ path 
+    Right xml -> return $ fromDocument xml
+  
+extractSheetIndex :: Archive -> Maybe [(T.Text, String)]
+extractSheetIndex ar = do
+  sheetXml <- findXMLEntry "xl/workbook.xml" ar
+  relXml <- findXMLEntry "xl/_rels/workbook.xml.rels" ar
+  return $ do
+    let relationships = relXml $.// laxElement "Relationship"
+        sheetListings =  sheetXml $.// laxElement "sheet"
+    sheetListingEntry <- sheetListings 
+    relationship <- relationships
+    guard $ (laxAttribute "Id") relationship == (laxAttribute "id") sheetListingEntry
+    sheetName <- (laxAttribute "Name") sheetListingEntry
+    target <- (laxAttribute "Target") relationship
+    return (sheetName, T.unpack $ mappend "xl/" target)
+
+extractSharedStrings :: Archive -> Maybe [T.Text]
+extractSharedStrings ar = do
+  sharedStringXml <- findXMLEntry "xl/sharedStrings.xml" ar
+  let entries = sharedStringXml $.// laxElement "si"
+  return $ map mconcat $ map (\e -> e $// laxElement "t" &/ content) entries
+
+parseCell :: Excelx -> Cursor -> Position -> Cell
+parseCell xlsx xmlSheet cellpos = 
+  let at = a1form cellpos 
+      cursor = xmlSheet $// laxElement "c" >=> attributeIs "r" at in
+  case listToMaybe cursor of
+    Nothing -> NoCell cellpos
+    Just c -> 
+        let formulaCell = do
+              formula <- listToMaybe $ cellContents "f" c
+              let valcell = fromMaybe (BlankCell cellpos) $ msum [textCell, numericCell, blankCell]
+              return $ FormulaCell cellpos formula valcell
+            textCell = do
+              textcell <- listToMaybe $ c $.// attributeIs "t" "s"
+              val <- listToMaybe $ cellContents "v" textcell
+              return $ TextCell cellpos (sharedStrings xlsx !! (read (T.unpack val)))
+            numericCell = do
+              v <- listToMaybe $ cellContents "v" c
+              return $ NumericCell cellpos (read $ T.unpack v)
+            blankCell = return $ BlankCell cellpos
+        in fromJust $ msum [formulaCell, textCell, numericCell, blankCell]
+      where
+        cellContents tag xml = xml $.// laxElement tag &.// content
+
+parseRow :: Excelx -> Cursor -> Int -> [Cell]
+parseRow xlsx sheetCur rownum = 
+    let rowxml = sheetCur $// laxElement "row" >=> attributeIs "r" (T.pack $ show rownum)
+        addrs = concatMap (\rx -> rx $// laxElement "c" >=> attribute "r") rowxml
+    in map (parseCell xlsx sheetCur) (map A1 addrs)
+
+maxRow :: Cursor -> Int
+maxRow sheetxml = foldr max 0 $ map (read . T.unpack) $ sheetxml $.// laxElement "row" >=> laxAttribute "r"
+
+extractSheet :: T.Text -> Excelx -> Maybe Cursor
+extractSheet sheetname xlsx = do
+  sheetPath <- lookup sheetname $ sheetIndex xlsx
+  findXMLEntry sheetPath $ archive xlsx
+  
+toExcelx :: BS.ByteString -> Maybe Excelx
+toExcelx bytes = do
+  let ar = toArchive bytes
+  sharedStringList <- extractSharedStrings ar
+  sheetIdx <- extractSheetIndex ar
+  return $ Excelx ar sharedStringList sheetIdx
+
+openExcelx :: FilePath -> IO (Maybe Excelx)
+openExcelx f = do
+  ar <- BS.readFile f
+  return $ toExcelx ar
+
+type Sheet = (Excelx, Cursor)
+type Row = [Cell]
+
+sheet :: MonadReader Excelx m => T.Text -> m (Maybe Sheet)
+sheet name = do
+  xlsx <- ask
+  let sheetx = extractSheet name xlsx
+  return $ fmap (\sheetxml -> (xlsx, sheetxml)) sheetx
+
+row :: MonadReader Sheet m => Int -> m Row
+row num = do
+  (xlsx, sheetx) <- ask
+  return $ parseRow xlsx sheetx num
+
+rows :: MonadReader Sheet m => m [Row]
+rows = do
+  (_, sheetx) <- ask
+  mapM row [1 .. maxRow sheetx]
+
+cell :: MonadReader Sheet m => Position -> m (Cell)  
+cell cellpos = do
+  (xlsx, sheetx) <- ask
+  return $ parseCell xlsx sheetx cellpos
+
+column :: MonadReader Sheet m => Int -> m [Cell]
+column colidx = do
+  (_, sheetx) <- ask
+  liftM catCells $ mapM cell $ map (flip R1C1 colidx) [1 .. maxRow sheetx]
+
+inExcel :: b -> Reader b c -> c
+inExcel = flip runReader
+
+inSheet :: MonadReader Excelx m => T.Text -> Reader Sheet a -> m (Maybe a)
+inSheet name action = do
+  maybeSheet <- sheet name
+  case maybeSheet of
+    Just sheetx -> return $ Just $ runReader action sheetx
+    Nothing -> return Nothing
+
+inExcelSheet :: Excelx -> T.Text -> Reader Sheet a -> Maybe a
+inExcelSheet xlsx name action = inExcel xlsx $ inSheet name action
