xlsx 0.4.1 → 0.4.2
raw patch · 9 files changed
+418/−39 lines, 9 files
Files
- CHANGELOG.markdown +9/−0
- src/Codec/Xlsx/Parser.hs +28/−1
- src/Codec/Xlsx/Types.hs +29/−12
- src/Codec/Xlsx/Types/AutoFilter.hs +165/−0
- src/Codec/Xlsx/Types/RichText.hs +7/−7
- src/Codec/Xlsx/Types/Table.hs +119/−0
- src/Codec/Xlsx/Writer.hs +33/−9
- test/DataTest.hs +19/−3
- xlsx.cabal +9/−7
CHANGELOG.markdown view
@@ -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
src/Codec/Xlsx/Parser.hs view
@@ -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 =
src/Codec/Xlsx/Types.hs view
@@ -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)
+ src/Codec/Xlsx/Types/AutoFilter.hs view
@@ -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"
src/Codec/Xlsx/Types/RichText.hs view
@@ -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
+ src/Codec/Xlsx/Types/Table.hs view
@@ -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+ ]+ ]
src/Codec/Xlsx/Writer.hs view
@@ -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))
test/DataTest.hs view
@@ -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
xlsx.cabal view
@@ -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