diff --git a/src/Codec/Xlsx/Util/Tabular.hs b/src/Codec/Xlsx/Util/Tabular.hs
--- a/src/Codec/Xlsx/Util/Tabular.hs
+++ b/src/Codec/Xlsx/Util/Tabular.hs
@@ -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
diff --git a/xlsx-tabular.cabal b/xlsx-tabular.cabal
--- a/xlsx-tabular.cabal
+++ b/xlsx-tabular.cabal
@@ -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
