diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,12 @@
+0.4.2
+-----
+* added basic tables support
+* fixed boolean element parsing for rich text run properties (thanks
+  laurent stephane <laurent_step@yahoo.fr> for reporting)
+* fixed problem of `cwStyle` not being optional (thanks laurent
+  stephane <laurent_step@yahoo.fr> for reporting)
+* added basic autofilter support
+
 0.4.1
 -----
 * fixed serialization problem of empty validations and pivot caches
diff --git a/src/Codec/Xlsx/Parser.hs b/src/Codec/Xlsx/Parser.hs
--- a/src/Codec/Xlsx/Parser.hs
+++ b/src/Codec/Xlsx/Parser.hs
@@ -157,6 +157,12 @@
       validations = M.fromList . map unDvPair $
           cur $/ element (n_ "dataValidations") &/ element (n_ "dataValidation") >=> fromCursor
 
+      tableIds =
+        cur $/ element (n_ "tableParts") &/ element (n_ "tablePart") >=>
+        fromAttribute (odr "id")
+
+  let mAutoFilter = listToMaybe $ cur $/ element (n_ "autoFilter") >=> fromCursor
+
   mDrawing <- case mDrawingId of
       Just dId -> do
           rel <- note (InvalidRef filePath dId) $ Relationships.lookup dId sheetRels
@@ -171,8 +177,25 @@
     note (InconsistentXlsx $ "Bad pivot table in " <> T.pack ptPath) $
       parsePivotTable (flip Prelude.lookup caches) bs
 
-  return $ Worksheet cws rowProps cells mDrawing merges sheetViews pageSetup condFormtattings validations pTables
+  tables <- forM tableIds $ \rId -> do
+    fp <- lookupRelPath filePath sheetRels rId
+    getTable ar fp
 
+  return $
+    Worksheet
+      cws
+      rowProps
+      cells
+      mDrawing
+      merges
+      sheetViews
+      pageSetup
+      condFormtattings
+      validations
+      pTables
+      mAutoFilter
+      tables
+
 extractCellValue :: SharedStringTable -> Text -> Text -> [CellValue]
 extractCellValue sst "s" v =
     case T.decimal v of
@@ -319,6 +342,10 @@
       return (cacheId, sources)
   return (sheets, DefinedNames names, caches)
 
+getTable :: Zip.Archive -> FilePath -> Parser Table
+getTable ar fp = do
+  cur <- xmlCursorRequired ar fp
+  headErr (InvalidFile fp) (fromCursor cur)
 
 worksheetFile :: FilePath -> Relationships -> Text -> RefId -> Parser WorksheetFile
 worksheetFile parentPath wbRels name rId =
diff --git a/src/Codec/Xlsx/Types.hs b/src/Codec/Xlsx/Types.hs
--- a/src/Codec/Xlsx/Types.hs
+++ b/src/Codec/Xlsx/Types.hs
@@ -32,6 +32,8 @@
     , wsConditionalFormattings
     , wsDataValidations
     , wsPivotTables
+    , wsAutoFilter
+    , wsTables
     -- ** Cells
     , cellValue
     , cellStyle
@@ -65,6 +67,7 @@
 import           Text.XML.Cursor
 
 import           Codec.Xlsx.Parser.Internal
+import           Codec.Xlsx.Types.AutoFilter            as X
 import           Codec.Xlsx.Types.Comment               as X
 import           Codec.Xlsx.Types.Common                as X
 import           Codec.Xlsx.Types.ConditionalFormatting as X
@@ -77,6 +80,7 @@
 import           Codec.Xlsx.Types.RichText              as X
 import           Codec.Xlsx.Types.SheetViews            as X
 import           Codec.Xlsx.Types.StyleSheet            as X
+import           Codec.Xlsx.Types.Table                 as X
 import           Codec.Xlsx.Types.Variant               as X
 import           Codec.Xlsx.Writer.Internal
 
@@ -129,19 +133,30 @@
 
 -- | Column range (from cwMin to cwMax) width
 data ColumnsWidth = ColumnsWidth
-    { cwMin   :: Int
-    , cwMax   :: Int
-    , cwWidth :: Double
-    , cwStyle :: Int
-    } deriving (Eq, Show)
+  { cwMin :: Int
+  -- ^ First column affected by this 'ColumnWidth' record.
+  , cwMax :: Int
+  -- ^ Last column affected by this 'ColumnWidth' record.
+  , cwWidth :: Double
+  -- ^ Column width measured as the number of characters of the
+  -- maximum digit width of the numbers 0, 1, 2, ..., 9 as rendered in
+  -- the normal style's font.
+  --
+  -- See longer description in Section 18.3.1.13 "col (Column Width &
+  -- Formatting)" (p. 1605)
+  , cwStyle :: Maybe Int
+  -- ^ Default style for the affected column(s). Affects cells not yet
+  -- allocated in the column(s).  In other words, this style applies
+  -- to new columns.
+  } deriving (Eq, Show)
 
 instance FromCursor ColumnsWidth where
-    fromCursor c = do
-      cwMin <- decimal =<< attribute "min" c
-      cwMax <- decimal =<< attribute "max" c
-      cwWidth <- rational =<< attribute "width" c
-      cwStyle <- decimal =<< attribute "style" c
-      return ColumnsWidth{..}
+  fromCursor c = do
+    cwMin <- fromAttribute "min" c
+    cwMax <- fromAttribute "max" c
+    cwWidth <- fromAttribute "width" c
+    cwStyle <- maybeAttribute "style" c
+    return ColumnsWidth {..}
 
 -- | Xlsx worksheet
 data Worksheet = Worksheet
@@ -155,12 +170,14 @@
   , _wsConditionalFormattings :: Map SqRef ConditionalFormatting
   , _wsDataValidations :: Map SqRef DataValidation
   , _wsPivotTables :: [PivotTable]
+  , _wsAutoFilter :: Maybe AutoFilter
+  , _wsTables :: [Table]
   } deriving (Eq, Show)
 
 makeLenses ''Worksheet
 
 instance Default Worksheet where
-    def = Worksheet [] M.empty M.empty Nothing [] Nothing Nothing M.empty M.empty []
+    def = Worksheet [] M.empty M.empty Nothing [] Nothing Nothing M.empty M.empty [] Nothing []
 
 newtype Styles = Styles {unStyles :: L.ByteString}
             deriving (Eq, Show)
diff --git a/src/Codec/Xlsx/Types/AutoFilter.hs b/src/Codec/Xlsx/Types/AutoFilter.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/Xlsx/Types/AutoFilter.hs
@@ -0,0 +1,165 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
+module Codec.Xlsx.Types.AutoFilter where
+
+import Control.Lens (makeLenses)
+import Data.Default
+import Data.Map (Map)
+import Data.Maybe (catMaybes)
+import qualified Data.Map as M
+import Data.Text (Text)
+import Text.XML
+import Text.XML.Cursor
+
+import Codec.Xlsx.Parser.Internal
+import Codec.Xlsx.Types.Common
+import Codec.Xlsx.Writer.Internal
+
+-- | The filterColumn collection identifies a particular column in the
+-- AutoFilter range and specifies filter information that has been
+-- applied to this column. If a column in the AutoFilter range has no
+-- criteria specified, then there is no corresponding filterColumn
+-- collection expressed for that column.
+--
+-- Section 18.3.2.7 "filterColumn (AutoFilter Column)" (p. 1717)
+data FilterColumn
+  = Filters { _fltValues :: [Text]}
+  | ACustomFilter CustomFilter
+  | CustomFiltersOr CustomFilter
+                    CustomFilter
+  | CustomFiltersAnd CustomFilter
+                     CustomFilter
+  deriving (Eq, Show)
+
+data CustomFilter = CustomFilter
+  { cfltOperator :: CustomFilterOperator
+  , cfltValue :: Text
+  } deriving (Eq, Show)
+
+data CustomFilterOperator
+  = FltrEqual
+    -- ^ Show results which are equal to criteria.
+  | FltrGreaterThan
+    -- ^ Show results which are greater than criteria.
+  | FltrGreaterThanOrEqual
+    -- ^ Show results which are greater than or equal to criteria.
+  | FltrLessThan
+    -- ^ Show results which are less than criteria.
+  | FltrLessThanOrEqual
+    -- ^ Show results which are less than or equal to criteria.
+  | FltrNotEqual
+    -- ^ Show results which are not equal to criteria.
+  deriving (Eq, Show)
+
+-- | AutoFilter temporarily hides rows based on a filter criteria,
+-- which is applied column by column to a table of datain the
+-- worksheet.
+--
+-- TODO: sortState, extList
+--
+-- Section 18.3.1.2 "autoFilter (AutoFilter Settings)" (p. 1596)
+data AutoFilter = AutoFilter
+  { _afRef :: Maybe CellRef
+  , _afFilterColumns :: Map Int FilterColumn
+  } deriving (Eq, Show)
+
+makeLenses ''AutoFilter
+
+
+{-------------------------------------------------------------------------------
+  Default instances
+-------------------------------------------------------------------------------}
+
+instance Default AutoFilter where
+    def = AutoFilter Nothing M.empty
+
+{-------------------------------------------------------------------------------
+  Parsing
+-------------------------------------------------------------------------------}
+
+instance FromCursor AutoFilter where
+  fromCursor cur = do
+    _afRef <- maybeAttribute "ref" cur
+    let _afFilterColumns = M.fromList $ cur $/ element (n_ "filterColumn") >=> \c -> do
+          colId <- fromAttribute "colId" c
+          fcol <- c $/ anyElement >=> fltColFromNode . node
+          return (colId, fcol)
+    return AutoFilter {..}
+
+fltColFromNode :: Node -> [FilterColumn]
+fltColFromNode n | n `nodeElNameIs` (n_ "filters") = do
+                     let _fltValues = cur $/ element (n_ "filter") >=> fromAttribute "val"
+                     return Filters{..}
+                 | n `nodeElNameIs` (n_ "customFilters") = do
+                     isAnd <- fromAttributeDef "and" False cur
+                     let cFilters = cur $/ element (n_ "customFilter") >=> \c -> do
+                           op <- fromAttributeDef "operator" FltrEqual c
+                           val <- fromAttribute "val" c
+                           return $ CustomFilter op val
+                     case cFilters of
+                       [f] ->
+                         return $ ACustomFilter f
+                       [f1, f2] ->
+                         if isAnd
+                           then return $ CustomFiltersAnd f1 f2
+                           else return $ CustomFiltersOr f1 f2
+                       _ ->
+                         fail "bad custom filter"
+                 | otherwise = fail "no matching nodes"
+  where
+    cur = fromNode n
+
+instance FromAttrVal CustomFilterOperator where
+  fromAttrVal "equal" = readSuccess FltrEqual
+  fromAttrVal "greaterThan" = readSuccess FltrGreaterThan
+  fromAttrVal "greaterThanOrEqual" = readSuccess FltrGreaterThanOrEqual
+  fromAttrVal "lessThan" = readSuccess FltrLessThan
+  fromAttrVal "lessThanOrEqual" = readSuccess FltrLessThanOrEqual
+  fromAttrVal "notEqual" = readSuccess FltrNotEqual
+  fromAttrVal t = invalidText "CustomFilterOperator" t
+
+{-------------------------------------------------------------------------------
+  Rendering
+-------------------------------------------------------------------------------}
+
+instance ToElement AutoFilter where
+  toElement nm AutoFilter {..} =
+    elementList
+      nm
+      (catMaybes ["ref" .=? _afRef])
+      [ elementList
+        (n_ "filterColumn")
+        ["colId" .= colId]
+        [fltColToElement fCol]
+      | (colId, fCol) <- M.toList _afFilterColumns
+      ]
+
+fltColToElement :: FilterColumn -> Element
+fltColToElement Filters {..} =
+  elementListSimple
+    (n_ "filters")
+    [leafElement (n_ "filter") ["val" .= v] | v <- _fltValues]
+fltColToElement (ACustomFilter f) =
+  elementListSimple (n_ "customFilters") [toElement (n_ "customFilter") f]
+fltColToElement (CustomFiltersOr f1 f2) =
+  elementListSimple
+    (n_ "customFilters")
+    [toElement (n_ "customFilter") f | f <- [f1, f2]]
+fltColToElement (CustomFiltersAnd f1 f2) =
+  elementList
+    (n_ "customFilters")
+    ["and" .= True]
+    [toElement (n_ "customFilter") f | f <- [f1, f2]]
+
+instance ToElement CustomFilter where
+  toElement nm CustomFilter {..} =
+    leafElement nm ["operator" .= cfltOperator, "val" .= cfltValue]
+
+instance ToAttrVal CustomFilterOperator where
+  toAttrVal FltrEqual = "equal"
+  toAttrVal FltrGreaterThan = "greaterThan"
+  toAttrVal FltrGreaterThanOrEqual = "greaterThanOrEqual"
+  toAttrVal FltrLessThan = "lessThan"
+  toAttrVal FltrLessThanOrEqual = "lessThanOrEqual"
+  toAttrVal FltrNotEqual = "notEqual"
diff --git a/src/Codec/Xlsx/Types/RichText.hs b/src/Codec/Xlsx/Types/RichText.hs
--- a/src/Codec/Xlsx/Types/RichText.hs
+++ b/src/Codec/Xlsx/Types/RichText.hs
@@ -265,13 +265,13 @@
     _runPropertiesFont          <- maybeElementValue (n_ "rFont") cur
     _runPropertiesCharset       <- maybeElementValue (n_ "charset") cur
     _runPropertiesFontFamily    <- maybeElementValue (n_ "family") cur
-    _runPropertiesBold          <- maybeElementValue (n_ "b") cur
-    _runPropertiesItalic        <- maybeElementValue (n_ "i") cur
-    _runPropertiesStrikeThrough <- maybeElementValue (n_ "strike") cur
-    _runPropertiesOutline       <- maybeElementValue (n_ "outline") cur
-    _runPropertiesShadow        <- maybeElementValue (n_ "shadow") cur
-    _runPropertiesCondense      <- maybeElementValue (n_ "condense") cur
-    _runPropertiesExtend        <- maybeElementValue (n_ "extend") cur
+    _runPropertiesBold          <- maybeBoolElementValue (n_ "b") cur
+    _runPropertiesItalic        <- maybeBoolElementValue (n_ "i") cur
+    _runPropertiesStrikeThrough <- maybeBoolElementValue (n_ "strike") cur
+    _runPropertiesOutline       <- maybeBoolElementValue (n_ "outline") cur
+    _runPropertiesShadow        <- maybeBoolElementValue (n_ "shadow") cur
+    _runPropertiesCondense      <- maybeBoolElementValue (n_ "condense") cur
+    _runPropertiesExtend        <- maybeBoolElementValue (n_ "extend") cur
     _runPropertiesColor         <- maybeFromElement  (n_ "color") cur
     _runPropertiesSize          <- maybeElementValue (n_ "sz") cur
     _runPropertiesUnderline     <- maybeElementValue (n_ "u") cur
diff --git a/src/Codec/Xlsx/Types/Table.hs b/src/Codec/Xlsx/Types/Table.hs
new file mode 100644
--- /dev/null
+++ b/src/Codec/Xlsx/Types/Table.hs
@@ -0,0 +1,119 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
+module Codec.Xlsx.Types.Table where
+
+import Control.Lens (makeLenses)
+import Data.Maybe (maybeToList)
+import Data.Text (Text)
+import Text.XML
+import Text.XML.Cursor
+
+#if !MIN_VERSION_base(4,8,0)
+import           Control.Applicative
+#endif
+
+import Codec.Xlsx.Parser.Internal
+import Codec.Xlsx.Types.AutoFilter
+import Codec.Xlsx.Types.Common
+import Codec.Xlsx.Writer.Internal
+
+-- | Tables are ranges of data in the worksheet that have special
+-- behavior applied which allow users to better sort, analyze, format,
+-- manage, add, and delete data. Tables and table columns can also be
+-- referenced through formulas by the spreadsheet application using
+-- friendly names, making formula calculations that use tables much
+-- easier to understand and maintain. Tables provide a natural way for
+-- working with large sets of tabular data.
+--
+-- NOTE: as @headerRowCount@ property isn't yet supported it's
+-- supposed that it's library user liability to guarantee that the 1st
+-- row of 'tblRef' range contains cells with names specified in
+-- `tblColumns`
+--
+-- Section 18.5 \"Tables\" (p. 1728)
+-- Section 18.5.1 \"Tables\" (p. 1729)
+-- Section 18.5.1.2 "table (Table)" (p. 1730)
+data Table = Table
+  { tblDisplayName :: Text
+    -- ^ A string representing the name of the table. This is the name
+    -- that shall be used in formula references, and displayed in the UI
+    -- to the spreadsheet user.  This name shall not have any spaces in
+    -- it, and it shall be unique amongst all other displayNames and
+    -- definedNames in the workbook. The character lengths and
+    -- restrictions are the same as for definedNames .
+  , tblName :: Text
+    -- ^ A string representing the name of the table that is used to
+    -- reference the table programmatically through the spreadsheet
+    -- applications object model. This string shall be unique per table
+    -- per sheet. It has the same length and character restrictions as
+    -- for displayName.  By default this should be the same as the
+    -- table's 'tblDisplayName' . This name should also be kept in synch with
+    -- the displayName when the displayName is updated in the UI by the
+    -- spreadsheet user.
+  , tblRef :: CellRef
+    -- ^ The range on the relevant sheet that the table occupies
+    -- expressed using A1 style referencing.
+  , tblColumns :: [TableColumn]
+    -- ^ columns of this table, specification requires any table to
+    -- include at least 1 column
+  , tblAutoFilter :: Maybe AutoFilter
+  } deriving (Eq, Show)
+
+-- | Single table column
+--
+-- TODO: styling information
+--
+-- Section 18.5.1.3 "tableColumn (Table Column)" (p. 1735)
+data TableColumn = TableColumn
+  { tblcName :: Text
+  -- ^ A string representing the unique caption of the table
+  -- column. This is what shall be displayed in the header row in the
+  -- UI, and is referenced through functions. This name shall be
+  -- unique per table.
+  } deriving (Eq, Show)
+
+makeLenses ''Table
+
+{-------------------------------------------------------------------------------
+  Parsing
+-------------------------------------------------------------------------------}
+
+instance FromCursor Table where
+  fromCursor c = do
+    tblDisplayName <- fromAttribute "displayName" c
+    tblName <- fromAttribute "name" c
+    tblRef <- fromAttribute "ref" c
+    tblAutoFilter <- maybeFromElement (n_ "autoFilter") c
+    let tblColumns =
+          c $/ element (n_ "tableColumns") &/ element (n_ "tableColumn") >=>
+          fmap TableColumn . fromAttribute "name"
+    return Table {..}
+
+{-------------------------------------------------------------------------------
+  Rendering
+-------------------------------------------------------------------------------}
+
+tableToDocument :: Table -> Int -> Document
+tableToDocument tbl i =
+  documentFromElement "Table generated by xlsx" $
+  tableToElement "table" tbl i
+
+tableToElement :: Name -> Table -> Int -> Element
+tableToElement nm Table {..} i = elementList nm attrs subElements
+  where
+    attrs =
+      [ "id" .= i
+      , "displayName" .= tblDisplayName
+      , "name" .= tblName
+      , "ref" .= tblRef
+      ]
+    subElements =
+      maybeToList (toElement "autoFilter" <$> tblAutoFilter) ++
+      [ countedElementList
+          "tableColumns"
+          [ leafElement "tableColumn" ["id" .= i', "name" .= tblcName c]
+          | (i', c) <- zip [(1 :: Int) ..] tblColumns
+          ]
+      ]
diff --git a/src/Codec/Xlsx/Writer.hs b/src/Codec/Xlsx/Writer.hs
--- a/src/Codec/Xlsx/Writer.hs
+++ b/src/Codec/Xlsx/Writer.hs
@@ -87,14 +87,24 @@
     workbookFiles = bookFiles xlsx
     sheetNames = xlsx ^. xlSheets . to (map fst)
 
-singleSheetFiles :: Int -> Cells -> [FileData] -> Worksheet -> (FileData, [FileData])
-singleSheetFiles n cells pivFileDatas ws = runST $ do
+singleSheetFiles :: Int
+                 -> Cells
+                 -> [FileData]
+                 -> Worksheet
+                 -> STRef s Int
+                 -> ST s (FileData, [FileData])
+singleSheetFiles n cells pivFileDatas ws tblIdRef = do
     ref <- newSTRef 1
     mCmntData <- genComments n cells ref
     mDrawingData <- maybe (return Nothing) (fmap Just . genDrawing n ref) (ws ^. wsDrawing)
     pivRefs <- forM pivFileDatas $ \fd -> do
       refId <- nextRefId ref
       return (refId, fd)
+    refTables <- forM (_wsTables ws) $ \tbl -> do
+      refId <- nextRefId ref
+      tblId <- readSTRef tblIdRef
+      modifySTRef' tblIdRef (+1)
+      return (refId, genTable tbl tblId)
     let sheetFilePath = "xl/worksheets/sheet" <> show n <> ".xml"
         sheetFile = FileData sheetFilePath
             "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"
@@ -108,19 +118,22 @@
             [ elementListSimple "sheetViews" . map (toElement "sheetView") <$> ws ^. wsSheetViews
             , nonEmptyElListSimple "cols" . map cwEl $ ws ^. wsColumns
             , Just . elementListSimple "sheetData" $ sheetDataXml cells (ws ^. wsRowPropertiesMap)
+            , toElement "autoFilter" <$> (ws ^. wsAutoFilter)
             , nonEmptyElListSimple "mergeCells" . map mergeE1 $ ws ^. wsMerges
             ] ++ map (Just . toElement "conditionalFormatting") cfPairs ++
             [ nonEmptyElListSimple "dataValidations" $ map (toElement "dataValidation") dvPairs
             , toElement "pageSetup" <$> ws ^. wsPageSetup
             , fst3 <$> mDrawingData
             , fst <$> mCmntData
+            , nonEmptyElListSimple "tableParts"
+                [leafElement "tablePart" [odr "id" .= rId] | (rId, _) <- refTables]
             ]
         cfPairs = map CfPair . M.toList $ ws ^. wsConditionalFormattings
         dvPairs = map DvPair . M.toList $ ws ^. wsDataValidations
-        cwEl cw = leafElement "col" [ ("min", txti $ cwMin cw)
-                                    , ("max", txti $ cwMax cw)
-                                    , ("width", txtd $ cwWidth cw)
-                                    , ("style", txti $ cwStyle cw)]
+        cwEl cw =
+          leafElement "col" $
+          ["min" .= cwMin cw, "max" .= cwMax cw, "width" .= cwWidth cw] ++
+          catMaybes ["style" .=? (justNonDef 0 =<< cwStyle cw)]
         mergeE1 r = leafElement "mergeCell" [("ref" .= r)]
 
         sheetRels = if null referencedFiles
@@ -133,7 +146,8 @@
             | (i, FileData{..}) <- referenced ]
         referenced = fromMaybe [] (snd <$> mCmntData) ++
                      catMaybes [ snd3 <$> mDrawingData ] ++
-                     pivRefs
+                     pivRefs ++
+                     refTables
         referencedFiles = map snd referenced
         extraFiles = maybe [] thd3 mDrawingData
         otherFiles = sheetRels ++ referencedFiles ++ extraFiles
@@ -208,7 +222,8 @@
   return (el, (rId, drawingFile), referenced)
   where
     drawingFilePath = "xl/drawings/drawing" <> show n <> ".xml"
-    drawingFile = FileData drawingFilePath (smlCT "drawing") "drawing" drawingXml
+    drawingCT = "application/vnd.openxmlformats-officedocument.drawing+xml"
+    drawingFile = FileData drawingFilePath drawingCT "drawing" drawingXml
     drawingXml = renderLBS def{rsNamespaces=nss} $ toDocument dr'
     nss = [ ("xdr", "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing")
           , ("a",   "http://schemas.openxmlformats.org/drawingml/2006/main")
@@ -322,6 +337,14 @@
             renderRels [refFileDataToRel tablePath (unsafeRefId 1, cacheFile)]
       in ((cacheId, cacheFile), tableFile, [tableRels])
 
+genTable :: Table -> Int -> FileData
+genTable tbl tblId = FileData{..}
+  where
+    fdPath = "xl/tables/table" <> show tblId <> ".xml"
+    fdContentType = smlCT "table"
+    fdRelType = "table"
+    fdContents = renderLBS def $ tableToDocument tbl tblId
+
 data FileData = FileData { fdPath        :: FilePath
                          , fdContentType :: Text
                          , fdRelType     :: Text
@@ -434,9 +457,10 @@
         generatePivotFiles (xlsx ^. xlSheets . to (map (^. _2 . wsPivotTables)))
       sheetCells = map (transformSheetData shared) sheets
       sheetInputs = zip3 sheetCells sheetPivotTables sheets
+  tblIdRef <- newSTRef 1
   allSheetFiles <- forM (zip [1..] sheetInputs) $ \(i, (cells, pvTables, sheet)) -> do
     rId <- nextRefId ref
-    let (sheetFile, others) = singleSheetFiles i cells pvTables sheet
+    (sheetFile, others) <- singleSheetFiles i cells pvTables sheet tblIdRef
     return ((rId, sheetFile), others)
   let sheetFiles = map fst allSheetFiles
       sheetNameByRId = zip (map fst sheetFiles) (xlsx ^. xlSheets . to (map fst))
diff --git a/test/DataTest.hs b/test/DataTest.hs
--- a/test/DataTest.hs
+++ b/test/DataTest.hs
@@ -111,7 +111,22 @@
   where
     sheets =
       [("List1", sheet1), ("Another sheet", sheet2), ("with pivot table", pvSheet)]
-    sheet1 = Worksheet cols rowProps testCellMap1 drawing ranges sheetViews pageSetup cFormatting validations []
+    sheet1 = Worksheet cols rowProps testCellMap1 drawing ranges
+      sheetViews pageSetup cFormatting validations [] (Just autoFilter) tables
+    autoFilter = def & afRef ?~ CellRef "A1:E10"
+                     & afFilterColumns .~ fCols
+    fCols = M.fromList [ (1, Filters ["a","b","ZZZ"])
+                       , (2, CustomFiltersAnd (CustomFilter FltrGreaterThanOrEqual "0")
+                           (CustomFilter FltrLessThan "42"))]
+    tables =
+      [ Table
+        { tblName = "Table1"
+        , tblDisplayName = "Table1"
+        , tblRef = CellRef "A3"
+        , tblColumns = [TableColumn "another text"]
+        , tblAutoFilter = Just (def & afRef ?~ CellRef "A3")
+        }
+      ]
     sheet2 = def & wsCells .~ testCellMap2
     pvSheet = sheetWithPvCells & wsPivotTables .~ [testPivotTable]
     sheetWithPvCells = flip execState def $ do
@@ -122,7 +137,7 @@
       cellValueAt (2, 3) ?= CellDouble 12.34
       cellValueAt (2, 4) ?= CellDouble 42
     rowProps = M.fromList [(1, RowProps (Just 50) (Just 3))]
-    cols = [ColumnsWidth 1 10 15 1]
+    cols = [ColumnsWidth 1 10 15 (Just 1)]
     drawing = Just $ testDrawing { _xdrAnchors = map resolve $ _xdrAnchors testDrawing }
     resolve :: Anchor RefId RefId -> Anchor FileInfo ChartSpace
     resolve Anchor {..} =
@@ -263,7 +278,8 @@
   where
     rich = [ RichTextRun
              { _richTextRunProperties =
-               Just $ def & runPropertiesCharset ?~ 1
+               Just $ def & runPropertiesBold ?~ True
+                          & runPropertiesCharset ?~ 1
                           & runPropertiesColor ?~ def -- TODO: why not Nothing here?
                           & runPropertiesFont ?~ "Calibri"
                           & runPropertiesScheme ?~ FontSchemeMinor
diff --git a/xlsx.cabal b/xlsx.cabal
--- a/xlsx.cabal
+++ b/xlsx.cabal
@@ -1,6 +1,6 @@
 Name:                xlsx
 
-Version:             0.4.1
+Version:             0.4.2
 
 Synopsis:            Simple and incomplete Excel file parser/writer
 Description:
@@ -35,6 +35,12 @@
   ghc-options:       -Wall
   Exposed-modules:   Codec.Xlsx
                    , Codec.Xlsx.Types
+                   , Codec.Xlsx.Formatted
+                   , Codec.Xlsx.Lens
+                   , Codec.Xlsx.Parser
+                   , Codec.Xlsx.Parser.Internal
+                   , Codec.Xlsx.Parser.Internal.PivotTable
+                   , Codec.Xlsx.Types.AutoFilter
                    , Codec.Xlsx.Types.Comment
                    , Codec.Xlsx.Types.Common
                    , Codec.Xlsx.Types.ConditionalFormatting
@@ -51,18 +57,14 @@
                    , Codec.Xlsx.Types.Internal.NumFmtPair
                    , Codec.Xlsx.Types.Internal.Relationships
                    , Codec.Xlsx.Types.Internal.SharedStringTable
+                   , Codec.Xlsx.Types.PageSetup
                    , Codec.Xlsx.Types.PivotTable
                    , Codec.Xlsx.Types.PivotTable.Internal
                    , Codec.Xlsx.Types.RichText
                    , Codec.Xlsx.Types.SheetViews
-                   , Codec.Xlsx.Types.PageSetup
                    , Codec.Xlsx.Types.StyleSheet
+                   , Codec.Xlsx.Types.Table
                    , Codec.Xlsx.Types.Variant
-                   , Codec.Xlsx.Lens
-                   , Codec.Xlsx.Parser
-                   , Codec.Xlsx.Parser.Internal
-                   , Codec.Xlsx.Parser.Internal.PivotTable
-                   , Codec.Xlsx.Formatted
                    , Codec.Xlsx.Writer
                    , Codec.Xlsx.Writer.Internal
                    , Codec.Xlsx.Writer.Internal.PivotTable
