{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE DeriveGeneric #-} module Codec.Xlsx.Types.SheetViews ( -- * Structured type to construct 'SheetViews' SheetView(..) , Selection(..) , Pane(..) , SheetViewType(..) , PaneType(..) , PaneState(..) -- * Lenses -- ** SheetView , sheetViewColorId , sheetViewDefaultGridColor , sheetViewRightToLeft , sheetViewShowFormulas , sheetViewShowGridLines , sheetViewShowOutlineSymbols , sheetViewShowRowColHeaders , sheetViewShowRuler , sheetViewShowWhiteSpace , sheetViewShowZeros , sheetViewTabSelected , sheetViewTopLeftCell , sheetViewType , sheetViewWindowProtection , sheetViewWorkbookViewId , sheetViewZoomScale , sheetViewZoomScaleNormal , sheetViewZoomScalePageLayoutView , sheetViewZoomScaleSheetLayoutView , sheetViewPane , sheetViewSelection -- ** Selection , selectionActiveCell , selectionActiveCellId , selectionPane , selectionSqref -- ** Pane , paneActivePane , paneState , paneTopLeftCell , paneXSplit , paneYSplit ) where import GHC.Generics (Generic) import Control.Lens (makeLenses) import Control.DeepSeq (NFData) import Data.Default import Data.Maybe (catMaybes, maybeToList, listToMaybe) import Text.XML import Text.XML.Cursor import qualified Data.Map as Map import Codec.Xlsx.Types.Common import Codec.Xlsx.Parser.Internal import Codec.Xlsx.Writer.Internal {------------------------------------------------------------------------------- Main types -------------------------------------------------------------------------------} -- | Worksheet view -- -- A single sheet view definition. When more than one sheet view is defined in -- the file, it means that when opening the workbook, each sheet view -- corresponds to a separate window within the spreadsheet application, where -- each window is showing the particular sheet containing the same -- workbookViewId value, the last sheetView definition is loaded, and the others -- are discarded. When multiple windows are viewing the same sheet, multiple -- sheetView elements (with corresponding workbookView entries) are saved. -- -- TODO: The @pivotSelection@ and @extLst@ child elements are unsupported. -- -- See Section 18.3.1.87 "sheetView (Worksheet View)" (p. 1880) data SheetView = SheetView { -- | Index to the color value for row/column text headings and gridlines. -- This is an 'index color value' (ICV) rather than rgb value. _sheetViewColorId :: Maybe Int -- | Flag indicating that the consuming application should use the default -- grid lines color (system dependent). Overrides any color specified in -- colorId. , _sheetViewDefaultGridColor :: Maybe Bool -- | Flag indicating whether the sheet is in 'right to left' display mode. -- When in this mode, Column A is on the far right, Column B ;is one column -- left of Column A, and so on. Also, information in cells is displayed in -- the Right to Left format. , _sheetViewRightToLeft :: Maybe Bool -- | Flag indicating whether this sheet should display formulas. , _sheetViewShowFormulas :: Maybe Bool -- | Flag indicating whether this sheet should display gridlines. , _sheetViewShowGridLines :: Maybe Bool -- | Flag indicating whether the sheet has outline symbols visible. This -- flag shall always override SheetPr element's outlinePr child element -- whose attribute is named showOutlineSymbols when there is a conflict. , _sheetViewShowOutlineSymbols :: Maybe Bool -- | Flag indicating whether the sheet should display row and column headings. , _sheetViewShowRowColHeaders :: Maybe Bool -- | Show the ruler in Page Layout View. , _sheetViewShowRuler :: Maybe Bool -- | Flag indicating whether page layout view shall display margins. False -- means do not display left, right, top (header), and bottom (footer) -- margins (even when there is data in the header or footer). , _sheetViewShowWhiteSpace :: Maybe Bool -- | Flag indicating whether the window should show 0 (zero) in cells -- containing zero value. When false, cells with zero value appear blank -- instead of showing the number zero. , _sheetViewShowZeros :: Maybe Bool -- | Flag indicating whether this sheet is selected. When only 1 sheet is -- selected and active, this value should be in synch with the activeTab -- value. In case of a conflict, the Start Part setting wins and sets the -- active sheet tab. -- -- Multiple sheets can be selected, but only one sheet shall be active at -- one time. , _sheetViewTabSelected :: Maybe Bool -- | Location of the top left visible cell Location of the top left visible -- cell in the bottom right pane (when in Left-to-Right mode). , _sheetViewTopLeftCell :: Maybe CellRef -- | Indicates the view type. , _sheetViewType :: Maybe SheetViewType -- | Flag indicating whether the panes in the window are locked due to -- workbook protection. This is an option when the workbook structure is -- protected. , _sheetViewWindowProtection :: Maybe Bool -- | Zero-based index of this workbook view, pointing to a workbookView -- element in the bookViews collection. -- -- NOTE: This attribute is required. , _sheetViewWorkbookViewId :: Int -- | Window zoom magnification for current view representing percent values. -- This attribute is restricted to values ranging from 10 to 400. Horizontal & -- Vertical scale together. , _sheetViewZoomScale :: Maybe Int -- | Zoom magnification to use when in normal view, representing percent -- values. This attribute is restricted to values ranging from 10 to 400. -- Horizontal & Vertical scale together. , _sheetViewZoomScaleNormal :: Maybe Int -- | Zoom magnification to use when in page layout view, representing -- percent values. This attribute is restricted to values ranging from 10 to -- 400. Horizontal & Vertical scale together. , _sheetViewZoomScalePageLayoutView :: Maybe Int -- | Zoom magnification to use when in page break preview, representing -- percent values. This attribute is restricted to values ranging from 10 to -- 400. Horizontal & Vertical scale together. , _sheetViewZoomScaleSheetLayoutView :: Maybe Int -- | Worksheet view pane , _sheetViewPane :: Maybe Pane -- | Worksheet view selection -- -- Minimum of 0, maximum of 4 elements , _sheetViewSelection :: [Selection] } deriving (Eq, Ord, Show, Generic) instance NFData SheetView -- | Worksheet view selection. -- -- Section 18.3.1.78 "selection (Selection)" (p. 1864) data Selection = Selection { -- | Location of the active cell _selectionActiveCell :: Maybe CellRef -- | 0-based index of the range reference (in the array of references listed -- in sqref) containing the active cell. Only used when the selection in -- sqref is not contiguous. Therefore, this value needs to be aware of the -- order in which the range references are written in sqref. -- -- When this value is out of range then activeCell can be used. , _selectionActiveCellId :: Maybe Int -- | The pane to which this selection belongs. , _selectionPane :: Maybe PaneType -- | Range of the selection. Can be non-contiguous set of ranges. , _selectionSqref :: Maybe SqRef } deriving (Eq, Ord, Show, Generic) instance NFData Selection -- | Worksheet view pane -- -- Section 18.3.1.66 "pane (View Pane)" (p. 1843) data Pane = Pane { -- | The pane that is active. _paneActivePane :: Maybe PaneType -- | Indicates whether the pane has horizontal / vertical splits, and -- whether those splits are frozen. , _paneState :: Maybe PaneState -- | Location of the top left visible cell in the bottom right pane (when in -- Left-To-Right mode). , _paneTopLeftCell :: Maybe CellRef -- | Horizontal position of the split, in 1/20th of a point; 0 (zero) if -- none. If the pane is frozen, this value indicates the number of columns -- visible in the top pane. , _paneXSplit :: Maybe Double -- | Vertical position of the split, in 1/20th of a point; 0 (zero) if none. -- If the pane is frozen, this value indicates the number of rows visible in -- the left pane. , _paneYSplit :: Maybe Double } deriving (Eq, Ord, Show, Generic) instance NFData Pane {------------------------------------------------------------------------------- Enumerations -------------------------------------------------------------------------------} -- | View setting of the sheet -- -- Section 18.18.69 "ST_SheetViewType (Sheet View Type)" (p. 2726) data SheetViewType = -- | Normal view SheetViewTypeNormal -- | Page break preview | SheetViewTypePageBreakPreview -- | Page layout view | SheetViewTypePageLayout deriving (Eq, Ord, Show, Generic) instance NFData SheetViewType -- | Pane type -- -- Section 18.18.52 "ST_Pane (Pane Types)" (p. 2710) data PaneType = -- | Bottom left pane, when both vertical and horizontal splits are applied. -- -- This value is also used when only a horizontal split has been applied, -- dividing the pane into upper and lower regions. In that case, this value -- specifies the bottom pane. PaneTypeBottomLeft -- Bottom right pane, when both vertical and horizontal splits are applied. | PaneTypeBottomRight -- | Top left pane, when both vertical and horizontal splits are applied. -- -- This value is also used when only a horizontal split has been applied, -- dividing the pane into upper and lower regions. In that case, this value -- specifies the top pane. -- -- This value is also used when only a vertical split has been applied, -- dividing the pane into right and left regions. In that case, this value -- specifies the left pane | PaneTypeTopLeft -- | Top right pane, when both vertical and horizontal splits are applied. -- -- This value is also used when only a vertical split has been applied, -- dividing the pane into right and left regions. In that case, this value -- specifies the right pane. | PaneTypeTopRight deriving (Eq, Ord, Show, Generic) instance NFData PaneType -- | State of the sheet's pane. -- -- Section 18.18.53 "ST_PaneState (Pane State)" (p. 2711) data PaneState = -- | Panes are frozen, but were not split being frozen. In this state, when -- the panes are unfrozen again, a single pane results, with no split. In -- this state, the split bars are not adjustable. PaneStateFrozen -- | Panes are frozen and were split before being frozen. In this state, -- when the panes are unfrozen again, the split remains, but is adjustable. | PaneStateFrozenSplit -- | Panes are split, but not frozen. In this state, the split bars are -- adjustable by the user. | PaneStateSplit deriving (Eq, Ord, Show, Generic) instance NFData PaneState {------------------------------------------------------------------------------- Lenses -------------------------------------------------------------------------------} makeLenses ''SheetView makeLenses ''Selection makeLenses ''Pane {------------------------------------------------------------------------------- Default instances -------------------------------------------------------------------------------} -- | NOTE: The 'Default' instance for 'SheetView' sets the required attribute -- '_sheetViewWorkbookViewId' to @0@. instance Default SheetView where def = SheetView { _sheetViewColorId = Nothing , _sheetViewDefaultGridColor = Nothing , _sheetViewRightToLeft = Nothing , _sheetViewShowFormulas = Nothing , _sheetViewShowGridLines = Nothing , _sheetViewShowOutlineSymbols = Nothing , _sheetViewShowRowColHeaders = Nothing , _sheetViewShowRuler = Nothing , _sheetViewShowWhiteSpace = Nothing , _sheetViewShowZeros = Nothing , _sheetViewTabSelected = Nothing , _sheetViewTopLeftCell = Nothing , _sheetViewType = Nothing , _sheetViewWindowProtection = Nothing , _sheetViewWorkbookViewId = 0 , _sheetViewZoomScale = Nothing , _sheetViewZoomScaleNormal = Nothing , _sheetViewZoomScalePageLayoutView = Nothing , _sheetViewZoomScaleSheetLayoutView = Nothing , _sheetViewPane = Nothing , _sheetViewSelection = [] } instance Default Selection where def = Selection { _selectionActiveCell = Nothing , _selectionActiveCellId = Nothing , _selectionPane = Nothing , _selectionSqref = Nothing } instance Default Pane where def = Pane { _paneActivePane = Nothing , _paneState = Nothing , _paneTopLeftCell = Nothing , _paneXSplit = Nothing , _paneYSplit = Nothing } {------------------------------------------------------------------------------- Rendering -------------------------------------------------------------------------------} -- | See @CT_SheetView@, p. 3913 instance ToElement SheetView where toElement nm SheetView{..} = Element { elementName = nm , elementNodes = map NodeElement . concat $ [ map (toElement "pane") (maybeToList _sheetViewPane) , map (toElement "selection") _sheetViewSelection -- TODO: pivotSelection -- TODO: extLst ] , elementAttributes = Map.fromList . catMaybes $ [ "windowProtection" .=? _sheetViewWindowProtection , "showFormulas" .=? _sheetViewShowFormulas , "showGridLines" .=? _sheetViewShowGridLines , "showRowColHeaders" .=? _sheetViewShowRowColHeaders , "showZeros" .=? _sheetViewShowZeros , "rightToLeft" .=? _sheetViewRightToLeft , "tabSelected" .=? _sheetViewTabSelected , "showRuler" .=? _sheetViewShowRuler , "showOutlineSymbols" .=? _sheetViewShowOutlineSymbols , "defaultGridColor" .=? _sheetViewDefaultGridColor , "showWhiteSpace" .=? _sheetViewShowWhiteSpace , "view" .=? _sheetViewType , "topLeftCell" .=? _sheetViewTopLeftCell , "colorId" .=? _sheetViewColorId , "zoomScale" .=? _sheetViewZoomScale , "zoomScaleNormal" .=? _sheetViewZoomScaleNormal , "zoomScaleSheetLayoutView" .=? _sheetViewZoomScaleSheetLayoutView , "zoomScalePageLayoutView" .=? _sheetViewZoomScalePageLayoutView , Just $ "workbookViewId" .= _sheetViewWorkbookViewId ] } -- | See @CT_Selection@, p. 3914 instance ToElement Selection where toElement nm Selection{..} = Element { elementName = nm , elementNodes = [] , elementAttributes = Map.fromList . catMaybes $ [ "pane" .=? _selectionPane , "activeCell" .=? _selectionActiveCell , "activeCellId" .=? _selectionActiveCellId , "sqref" .=? _selectionSqref ] } -- | See @CT_Pane@, p. 3913 instance ToElement Pane where toElement nm Pane{..} = Element { elementName = nm , elementNodes = [] , elementAttributes = Map.fromList . catMaybes $ [ "xSplit" .=? _paneXSplit , "ySplit" .=? _paneYSplit , "topLeftCell" .=? _paneTopLeftCell , "activePane" .=? _paneActivePane , "state" .=? _paneState ] } -- | See @ST_SheetViewType@, p. 3913 instance ToAttrVal SheetViewType where toAttrVal SheetViewTypeNormal = "normal" toAttrVal SheetViewTypePageBreakPreview = "pageBreakPreview" toAttrVal SheetViewTypePageLayout = "pageLayout" -- | See @ST_Pane@, p. 3914 instance ToAttrVal PaneType where toAttrVal PaneTypeBottomRight = "bottomRight" toAttrVal PaneTypeTopRight = "topRight" toAttrVal PaneTypeBottomLeft = "bottomLeft" toAttrVal PaneTypeTopLeft = "topLeft" -- | See @ST_PaneState@, p. 3929 instance ToAttrVal PaneState where toAttrVal PaneStateSplit = "split" toAttrVal PaneStateFrozen = "frozen" toAttrVal PaneStateFrozenSplit = "frozenSplit" {------------------------------------------------------------------------------- Parsing -------------------------------------------------------------------------------} -- | See @CT_SheetView@, p. 3913 instance FromCursor SheetView where fromCursor cur = do _sheetViewWindowProtection <- maybeAttribute "windowProtection" cur _sheetViewShowFormulas <- maybeAttribute "showFormulas" cur _sheetViewShowGridLines <- maybeAttribute "showGridLines" cur _sheetViewShowRowColHeaders <- maybeAttribute "showRowColHeaders"cur _sheetViewShowZeros <- maybeAttribute "showZeros" cur _sheetViewRightToLeft <- maybeAttribute "rightToLeft" cur _sheetViewTabSelected <- maybeAttribute "tabSelected" cur _sheetViewShowRuler <- maybeAttribute "showRuler" cur _sheetViewShowOutlineSymbols <- maybeAttribute "showOutlineSymbols" cur _sheetViewDefaultGridColor <- maybeAttribute "defaultGridColor" cur _sheetViewShowWhiteSpace <- maybeAttribute "showWhiteSpace" cur _sheetViewType <- maybeAttribute "view" cur _sheetViewTopLeftCell <- maybeAttribute "topLeftCell" cur _sheetViewColorId <- maybeAttribute "colorId" cur _sheetViewZoomScale <- maybeAttribute "zoomScale" cur _sheetViewZoomScaleNormal <- maybeAttribute "zoomScaleNormal" cur _sheetViewZoomScaleSheetLayoutView <- maybeAttribute "zoomScaleSheetLayoutView" cur _sheetViewZoomScalePageLayoutView <- maybeAttribute "zoomScalePageLayoutView" cur _sheetViewWorkbookViewId <- fromAttribute "workbookViewId" cur let _sheetViewPane = listToMaybe $ cur $/ element (n_ "pane") >=> fromCursor _sheetViewSelection = cur $/ element (n_ "selection") >=> fromCursor return SheetView{..} instance FromXenoNode SheetView where fromXenoNode root = parseAttributes root $ do _sheetViewWindowProtection <- maybeAttr "windowProtection" _sheetViewShowFormulas <- maybeAttr "showFormulas" _sheetViewShowGridLines <- maybeAttr "showGridLines" _sheetViewShowRowColHeaders <- maybeAttr "showRowColHeaders" _sheetViewShowZeros <- maybeAttr "showZeros" _sheetViewRightToLeft <- maybeAttr "rightToLeft" _sheetViewTabSelected <- maybeAttr "tabSelected" _sheetViewShowRuler <- maybeAttr "showRuler" _sheetViewShowOutlineSymbols <- maybeAttr "showOutlineSymbols" _sheetViewDefaultGridColor <- maybeAttr "defaultGridColor" _sheetViewShowWhiteSpace <- maybeAttr "showWhiteSpace" _sheetViewType <- maybeAttr "view" _sheetViewTopLeftCell <- maybeAttr "topLeftCell" _sheetViewColorId <- maybeAttr "colorId" _sheetViewZoomScale <- maybeAttr "zoomScale" _sheetViewZoomScaleNormal <- maybeAttr "zoomScaleNormal" _sheetViewZoomScaleSheetLayoutView <- maybeAttr "zoomScaleSheetLayoutView" _sheetViewZoomScalePageLayoutView <- maybeAttr "zoomScalePageLayoutView" _sheetViewWorkbookViewId <- fromAttr "workbookViewId" (_sheetViewPane, _sheetViewSelection) <- toAttrParser . collectChildren root $ (,) <$> maybeFromChild "pane" <*> fromChildList "selection" return SheetView {..} -- | See @CT_Pane@, p. 3913 instance FromCursor Pane where fromCursor cur = do _paneXSplit <- maybeAttribute "xSplit" cur _paneYSplit <- maybeAttribute "ySplit" cur _paneTopLeftCell <- maybeAttribute "topLeftCell" cur _paneActivePane <- maybeAttribute "activePane" cur _paneState <- maybeAttribute "state" cur return Pane{..} instance FromXenoNode Pane where fromXenoNode root = parseAttributes root $ do _paneXSplit <- maybeAttr "xSplit" _paneYSplit <- maybeAttr "ySplit" _paneTopLeftCell <- maybeAttr "topLeftCell" _paneActivePane <- maybeAttr "activePane" _paneState <- maybeAttr "state" return Pane {..} -- | See @CT_Selection@, p. 3914 instance FromCursor Selection where fromCursor cur = do _selectionPane <- maybeAttribute "pane" cur _selectionActiveCell <- maybeAttribute "activeCell" cur _selectionActiveCellId <- maybeAttribute "activeCellId" cur _selectionSqref <- maybeAttribute "sqref" cur return Selection{..} instance FromXenoNode Selection where fromXenoNode root = parseAttributes root $ do _selectionPane <- maybeAttr "pane" _selectionActiveCell <- maybeAttr "activeCell" _selectionActiveCellId <- maybeAttr "activeCellId" _selectionSqref <- maybeAttr "sqref" return Selection {..} -- | See @ST_SheetViewType@, p. 3913 instance FromAttrVal SheetViewType where fromAttrVal "normal" = readSuccess SheetViewTypeNormal fromAttrVal "pageBreakPreview" = readSuccess SheetViewTypePageBreakPreview fromAttrVal "pageLayout" = readSuccess SheetViewTypePageLayout fromAttrVal t = invalidText "SheetViewType" t instance FromAttrBs SheetViewType where fromAttrBs "normal" = return SheetViewTypeNormal fromAttrBs "pageBreakPreview" = return SheetViewTypePageBreakPreview fromAttrBs "pageLayout" = return SheetViewTypePageLayout fromAttrBs x = unexpectedAttrBs "SheetViewType" x -- | See @ST_Pane@, p. 3914 instance FromAttrVal PaneType where fromAttrVal "bottomRight" = readSuccess PaneTypeBottomRight fromAttrVal "topRight" = readSuccess PaneTypeTopRight fromAttrVal "bottomLeft" = readSuccess PaneTypeBottomLeft fromAttrVal "topLeft" = readSuccess PaneTypeTopLeft fromAttrVal t = invalidText "PaneType" t instance FromAttrBs PaneType where fromAttrBs "bottomRight" = return PaneTypeBottomRight fromAttrBs "topRight" = return PaneTypeTopRight fromAttrBs "bottomLeft" = return PaneTypeBottomLeft fromAttrBs "topLeft" = return PaneTypeTopLeft fromAttrBs x = unexpectedAttrBs "PaneType" x -- | See @ST_PaneState@, p. 3929 instance FromAttrVal PaneState where fromAttrVal "split" = readSuccess PaneStateSplit fromAttrVal "frozen" = readSuccess PaneStateFrozen fromAttrVal "frozenSplit" = readSuccess PaneStateFrozenSplit fromAttrVal t = invalidText "PaneState" t instance FromAttrBs PaneState where fromAttrBs "split" = return PaneStateSplit fromAttrBs "frozen" = return PaneStateFrozen fromAttrBs "frozenSplit" = return PaneStateFrozenSplit fromAttrBs x = unexpectedAttrBs "PaneState" x