2
2
{-# LANGUAGE DeriveGeneric #-}
3
3
{-# LANGUAGE RankNTypes #-}
4
4
{-# LANGUAGE RecordWildCards #-}
5
- {-# LANGUAGE TemplateHaskell #-}
6
5
7
6
-- | Higher level interface for creating styled worksheets
8
7
module Codec.Xlsx.Formatted
@@ -14,30 +13,6 @@ module Codec.Xlsx.Formatted
14
13
toFormattedCells ,
15
14
CondFormatted (.. ),
16
15
conditionallyFormatted ,
17
-
18
- -- * Lenses
19
-
20
- -- ** Format
21
- formatAlignment ,
22
- formatBorder ,
23
- formatFill ,
24
- formatFont ,
25
- formatNumberFormat ,
26
- formatProtection ,
27
- formatPivotButton ,
28
- formatQuotePrefix ,
29
-
30
- -- ** FormattedCell
31
- formattedCell ,
32
- formattedFormat ,
33
- formattedColSpan ,
34
- formattedRowSpan ,
35
-
36
- -- ** FormattedCondFmt
37
- condfmtCondition ,
38
- condfmtDxf ,
39
- condfmtPriority ,
40
- condfmtStopIfTrue ,
41
16
)
42
17
where
43
18
@@ -55,6 +30,7 @@ import Control.Monad.State hiding (forM_, mapM)
55
30
import Data.Default
56
31
import Data.Foldable (asum , forM_ )
57
32
import Data.Function (on )
33
+ import Data.Generics.Labels
58
34
import Data.List (foldl' , groupBy , sortBy )
59
35
import Data.Map (Map )
60
36
import qualified Data.Map as M
@@ -71,26 +47,25 @@ import Prelude hiding (mapM)
71
47
-------------------------------------------------------------------------------}
72
48
73
49
data FormattingState = FormattingState
74
- { _formattingBorders :: Map Border Int ,
75
- _formattingCellXfs :: Map CellXf Int ,
76
- _formattingFills :: Map Fill Int ,
77
- _formattingFonts :: Map Font Int ,
78
- _formattingNumFmts :: Map Text Int ,
50
+ { formattingBorders :: Map Border Int ,
51
+ formattingCellXfs :: Map CellXf Int ,
52
+ formattingFills :: Map Fill Int ,
53
+ formattingFonts :: Map Font Int ,
54
+ formattingNumFmts :: Map Text Int ,
79
55
-- | In reverse order
80
- _formattingMerges :: [Range ]
56
+ formattingMerges :: [Range ]
81
57
}
82
-
83
- makeLenses ''FormattingState
58
+ deriving stock (Generic )
84
59
85
60
stateFromStyleSheet :: StyleSheet -> FormattingState
86
61
stateFromStyleSheet StyleSheet {.. } =
87
62
FormattingState
88
- { _formattingBorders = fromValueList _styleSheetBorders,
89
- _formattingCellXfs = fromValueList _styleSheetCellXfs,
90
- _formattingFills = fromValueList _styleSheetFills,
91
- _formattingFonts = fromValueList _styleSheetFonts,
92
- _formattingNumFmts = M. fromList . map swap $ M. toList _styleSheetNumFmts,
93
- _formattingMerges = []
63
+ { formattingBorders = fromValueList _styleSheetBorders,
64
+ formattingCellXfs = fromValueList _styleSheetCellXfs,
65
+ formattingFills = fromValueList _styleSheetFills,
66
+ formattingFonts = fromValueList _styleSheetFonts,
67
+ formattingNumFmts = M. fromList . map swap $ M. toList _styleSheetNumFmts,
68
+ formattingMerges = []
94
69
}
95
70
96
71
fromValueList :: (Ord a ) => [a ] -> Map a Int
@@ -102,11 +77,11 @@ toValueList = map snd . sortBy (comparing fst) . map swap . M.toList
102
77
updateStyleSheetFromState :: StyleSheet -> FormattingState -> StyleSheet
103
78
updateStyleSheetFromState sSheet FormattingState {.. } =
104
79
sSheet
105
- { _styleSheetBorders = toValueList _formattingBorders ,
106
- _styleSheetCellXfs = toValueList _formattingCellXfs ,
107
- _styleSheetFills = toValueList _formattingFills ,
108
- _styleSheetFonts = toValueList _formattingFonts ,
109
- _styleSheetNumFmts = M. fromList . map swap $ M. toList _formattingNumFmts
80
+ { _styleSheetBorders = toValueList formattingBorders ,
81
+ _styleSheetCellXfs = toValueList formattingCellXfs ,
82
+ _styleSheetFills = toValueList formattingFills ,
83
+ _styleSheetFonts = toValueList formattingFonts ,
84
+ _styleSheetNumFmts = M. fromList . map swap $ M. toList formattingNumFmts
110
85
}
111
86
112
87
getId ::
@@ -133,15 +108,13 @@ getId' k f v = do
133
108
-------------------------------------------------------------------------------}
134
109
135
110
data FormattedCondFmt = FormattedCondFmt
136
- { _condfmtCondition :: Condition ,
137
- _condfmtDxf :: Dxf ,
138
- _condfmtPriority :: Int ,
139
- _condfmtStopIfTrue :: Maybe Bool
111
+ { condfmtCondition :: Condition ,
112
+ condfmtDxf :: Dxf ,
113
+ condfmtPriority :: Int ,
114
+ condfmtStopIfTrue :: Maybe Bool
140
115
}
141
116
deriving (Eq , Show , Generic )
142
117
143
- makeLenses ''FormattedCondFmt
144
-
145
118
{- ------------------------------------------------------------------------------
146
119
Cell with formatting
147
120
-------------------------------------------------------------------------------}
@@ -153,56 +126,52 @@ makeLenses ''FormattedCondFmt
153
126
-- * Add a number format ('_cellXfApplyNumberFormat', '_cellXfNumFmtId')
154
127
-- * Add references to the named style sheets ('_cellXfId')
155
128
data Format = Format
156
- { _formatAlignment :: Maybe Alignment ,
157
- _formatBorder :: Maybe Border ,
158
- _formatFill :: Maybe Fill ,
159
- _formatFont :: Maybe Font ,
160
- _formatNumberFormat :: Maybe NumberFormat ,
161
- _formatProtection :: Maybe Protection ,
162
- _formatPivotButton :: Maybe Bool ,
163
- _formatQuotePrefix :: Maybe Bool
129
+ { formatAlignment :: Maybe Alignment ,
130
+ formatBorder :: Maybe Border ,
131
+ formatFill :: Maybe Fill ,
132
+ formatFont :: Maybe Font ,
133
+ formatNumberFormat :: Maybe NumberFormat ,
134
+ formatProtection :: Maybe Protection ,
135
+ formatPivotButton :: Maybe Bool ,
136
+ formatQuotePrefix :: Maybe Bool
164
137
}
165
138
deriving (Eq , Show , Generic )
166
139
167
- makeLenses ''Format
168
-
169
- -- | Cell with formatting. '_cellStyle' property of '_formattedCell' is ignored
140
+ -- | Cell with formatting. '_cellStyle' property of 'formattedCell' is ignored
170
141
--
171
142
-- See 'formatted' for more details.
172
143
data FormattedCell = FormattedCell
173
- { _formattedCell :: Cell ,
174
- _formattedFormat :: Format ,
175
- _formattedColSpan :: Int ,
176
- _formattedRowSpan :: Int
144
+ { formattedCell :: Cell ,
145
+ formattedFormat :: Format ,
146
+ formattedColSpan :: Int ,
147
+ formattedRowSpan :: Int
177
148
}
178
149
deriving (Eq , Show , Generic )
179
150
180
- makeLenses ''FormattedCell
181
-
182
151
{- ------------------------------------------------------------------------------
183
152
Default instances
184
153
-------------------------------------------------------------------------------}
185
154
186
155
instance Default FormattedCell where
187
156
def =
188
157
FormattedCell
189
- { _formattedCell = def,
190
- _formattedFormat = def,
191
- _formattedColSpan = 1 ,
192
- _formattedRowSpan = 1
158
+ { formattedCell = def,
159
+ formattedFormat = def,
160
+ formattedColSpan = 1 ,
161
+ formattedRowSpan = 1
193
162
}
194
163
195
164
instance Default Format where
196
165
def =
197
166
Format
198
- { _formatAlignment = Nothing ,
199
- _formatBorder = Nothing ,
200
- _formatFill = Nothing ,
201
- _formatFont = Nothing ,
202
- _formatNumberFormat = Nothing ,
203
- _formatProtection = Nothing ,
204
- _formatPivotButton = Nothing ,
205
- _formatQuotePrefix = Nothing
167
+ { formatAlignment = Nothing ,
168
+ formatBorder = Nothing ,
169
+ formatFill = Nothing ,
170
+ formatFont = Nothing ,
171
+ formatNumberFormat = Nothing ,
172
+ formatProtection = Nothing ,
173
+ formatPivotButton = Nothing ,
174
+ formatQuotePrefix = Nothing
206
175
}
207
176
208
177
instance Default FormattedCondFmt where
@@ -259,7 +228,7 @@ formatted cs styleSheet =
259
228
in Formatted
260
229
{ formattedCellMap = M. fromList (concat cs'),
261
230
formattedStyleSheet = styleSheet',
262
- formattedMerges = reverse (finalSt ^. formattingMerges)
231
+ formattedMerges = reverse (finalSt ^. # formattingMerges)
263
232
}
264
233
265
234
-- | Build an 'Xlsx', render provided cells as per the 'StyleSheet'.
@@ -271,7 +240,7 @@ formatWorkbook nfcss initStyle = extract go
271
240
go = flip runState initSt $
272
241
forM nfcss $ \ (name, fcs) -> do
273
242
cs' <- forM (M. toList fcs) $ \ (rc, fc) -> formatCell rc fc
274
- merges <- reverse . _formattingMerges <$> get
243
+ merges <- reverse . formattingMerges <$> get
275
244
return
276
245
( name,
277
246
def
@@ -295,30 +264,30 @@ toFormattedCells m merges StyleSheet {..} = applyMerges $ M.map toFormattedCell
295
264
where
296
265
toFormattedCell cell@ Cell {.. } =
297
266
FormattedCell
298
- { _formattedCell = cell {_cellStyle = Nothing }, -- just to remove confusion
299
- _formattedFormat =
267
+ { formattedCell = cell {_cellStyle = Nothing }, -- just to remove confusion
268
+ formattedFormat =
300
269
maybe def formatFromStyle $ flip M. lookup cellXfs =<< _cellStyle,
301
- _formattedColSpan = 1 ,
302
- _formattedRowSpan = 1
270
+ formattedColSpan = 1 ,
271
+ formattedRowSpan = 1
303
272
}
304
273
formatFromStyle cellXf =
305
274
Format
306
- { _formatAlignment = applied _cellXfApplyAlignment _cellXfAlignment cellXf,
307
- _formatBorder =
275
+ { formatAlignment = applied _cellXfApplyAlignment _cellXfAlignment cellXf,
276
+ formatBorder =
308
277
flip M. lookup borders
309
278
=<< applied _cellXfApplyBorder _cellXfBorderId cellXf,
310
- _formatFill =
279
+ formatFill =
311
280
flip M. lookup fills
312
281
=<< applied _cellXfApplyFill _cellXfFillId cellXf,
313
- _formatFont =
282
+ formatFont =
314
283
flip M. lookup fonts
315
284
=<< applied _cellXfApplyFont _cellXfFontId cellXf,
316
- _formatNumberFormat =
285
+ formatNumberFormat =
317
286
lookupNumFmt
318
287
=<< applied _cellXfApplyNumberFormat _cellXfNumFmtId cellXf,
319
- _formatProtection = _cellXfProtection cellXf,
320
- _formatPivotButton = _cellXfPivotButton cellXf,
321
- _formatQuotePrefix = _cellXfQuotePrefix cellXf
288
+ formatProtection = _cellXfProtection cellXf,
289
+ formatPivotButton = _cellXfPivotButton cellXf,
290
+ formatQuotePrefix = _cellXfQuotePrefix cellXf
322
291
}
323
292
idMapped :: [a ] -> Map Int a
324
293
idMapped = M. fromList . zip [0 .. ]
@@ -343,11 +312,11 @@ toFormattedCells m merges StyleSheet {..} = applyMerges $ M.map toFormattedCell
343
312
forM_ nonTopLeft (modify . M. delete)
344
313
at (r1, c1)
345
314
. non def
346
- . formattedRowSpan
315
+ . # formattedRowSpan
347
316
.= (unRowIndex r2 - unRowIndex r1 + 1 )
348
317
at (r1, c1)
349
318
. non def
350
- . formattedColSpan
319
+ . # formattedColSpan
351
320
.= (unColumnIndex c2 - unColumnIndex c1 + 1 )
352
321
353
322
data CondFormatted = CondFormatted
@@ -391,15 +360,15 @@ formatCell ::
391
360
State FormattingState [((RowIndex , ColumnIndex ), Cell )]
392
361
formatCell (row, col) cell = do
393
362
let (block, mMerge) = cellBlock (row, col) cell
394
- forM_ mMerge $ \ merge -> formattingMerges %= (:) merge
363
+ forM_ mMerge $ \ merge -> # formattingMerges %= (:) merge
395
364
mapM go block
396
365
where
397
366
go ::
398
367
((RowIndex , ColumnIndex ), FormattedCell ) ->
399
368
State FormattingState ((RowIndex , ColumnIndex ), Cell )
400
369
go (pos, c@ FormattedCell {.. }) = do
401
370
styleId <- cellStyleId c
402
- return (pos, _formattedCell {_cellStyle = styleId})
371
+ return (pos, formattedCell {_cellStyle = styleId})
403
372
404
373
-- | Cell block corresponding to a single 'FormattedCell'
405
374
--
@@ -432,9 +401,9 @@ cellBlock (row, col) cell@FormattedCell {..} = (block, merge)
432
401
cellAt (row', col') =
433
402
if row' == row && col == col'
434
403
then cell
435
- else def & formattedFormat . formatBorder ?~ borderAt (row', col')
404
+ else def & # formattedFormat . # formatBorder ?~ borderAt (row', col')
436
405
437
- border = _formatBorder _formattedFormat
406
+ border = formatBorder formattedFormat
438
407
439
408
borderAt :: (RowIndex , ColumnIndex ) -> Border
440
409
borderAt (row', col') =
@@ -451,42 +420,42 @@ cellBlock (row, col) cell@FormattedCell {..} = (block, merge)
451
420
topRow , bottomRow :: RowIndex
452
421
leftCol , rightCol :: ColumnIndex
453
422
topRow = row
454
- bottomRow = RowIndex $ unRowIndex row + _formattedRowSpan - 1
423
+ bottomRow = RowIndex $ unRowIndex row + formattedRowSpan - 1
455
424
leftCol = col
456
- rightCol = ColumnIndex $ unColumnIndex col + _formattedColSpan - 1
425
+ rightCol = ColumnIndex $ unColumnIndex col + formattedColSpan - 1
457
426
458
427
cellStyleId :: FormattedCell -> State FormattingState (Maybe Int )
459
- cellStyleId c = mapM (getId formattingCellXfs) =<< constructCellXf c
428
+ cellStyleId c = mapM (getId # formattingCellXfs) =<< constructCellXf c
460
429
461
430
constructCellXf :: FormattedCell -> State FormattingState (Maybe CellXf )
462
- constructCellXf FormattedCell {_formattedFormat = Format {.. }} = do
463
- mBorderId <- getId formattingBorders `mapM` _formatBorder
464
- mFillId <- getId formattingFills `mapM` _formatFill
465
- mFontId <- getId formattingFonts `mapM` _formatFont
431
+ constructCellXf FormattedCell {formattedFormat = Format {.. }} = do
432
+ mBorderId <- getId # formattingBorders `mapM` formatBorder
433
+ mFillId <- getId # formattingFills `mapM` formatFill
434
+ mFontId <- getId # formattingFonts `mapM` formatFont
466
435
let getFmtId ::
467
436
Lens' FormattingState (Map Text Int ) ->
468
437
NumberFormat ->
469
438
State FormattingState Int
470
439
getFmtId _ (StdNumberFormat fmt) = return (stdNumberFormatId fmt)
471
440
getFmtId l (UserNumberFormat fmt) = getId' firstUserNumFmtId l fmt
472
- mNumFmtId <- getFmtId formattingNumFmts `mapM` _formatNumberFormat
441
+ mNumFmtId <- getFmtId # formattingNumFmts `mapM` formatNumberFormat
473
442
let xf =
474
443
CellXf
475
- { _cellXfApplyAlignment = apply _formatAlignment ,
444
+ { _cellXfApplyAlignment = apply formatAlignment ,
476
445
_cellXfApplyBorder = apply mBorderId,
477
446
_cellXfApplyFill = apply mFillId,
478
447
_cellXfApplyFont = apply mFontId,
479
- _cellXfApplyNumberFormat = apply _formatNumberFormat ,
480
- _cellXfApplyProtection = apply _formatProtection ,
448
+ _cellXfApplyNumberFormat = apply formatNumberFormat ,
449
+ _cellXfApplyProtection = apply formatProtection ,
481
450
_cellXfBorderId = mBorderId,
482
451
_cellXfFillId = mFillId,
483
452
_cellXfFontId = mFontId,
484
453
_cellXfNumFmtId = mNumFmtId,
485
- _cellXfPivotButton = _formatPivotButton ,
486
- _cellXfQuotePrefix = _formatQuotePrefix ,
454
+ _cellXfPivotButton = formatPivotButton ,
455
+ _cellXfQuotePrefix = formatQuotePrefix ,
487
456
_cellXfId = Nothing , -- TODO
488
- _cellXfAlignment = _formatAlignment ,
489
- _cellXfProtection = _formatProtection
457
+ _cellXfAlignment = formatAlignment ,
458
+ _cellXfProtection = formatProtection
490
459
}
491
460
return $ if xf == def then Nothing else Just xf
492
461
where
@@ -499,17 +468,17 @@ constructCellXf FormattedCell {_formattedFormat = Format {..}} = do
499
468
mapDxf :: FormattedCondFmt -> State (Map Dxf Int ) CfRule
500
469
mapDxf FormattedCondFmt {.. } = do
501
470
dxf2id <- get
502
- dxfId <- case M. lookup _condfmtDxf dxf2id of
471
+ dxfId <- case M. lookup condfmtDxf dxf2id of
503
472
Just i ->
504
473
return i
505
474
Nothing -> do
506
475
let newId = M. size dxf2id
507
- modify $ M. insert _condfmtDxf newId
476
+ modify $ M. insert condfmtDxf newId
508
477
return newId
509
478
return
510
479
CfRule
511
- { _cfrCondition = _condfmtCondition ,
480
+ { _cfrCondition = condfmtCondition ,
512
481
_cfrDxfId = Just dxfId,
513
- _cfrPriority = _condfmtPriority ,
514
- _cfrStopIfTrue = _condfmtStopIfTrue
482
+ _cfrPriority = condfmtPriority ,
483
+ _cfrStopIfTrue = condfmtStopIfTrue
515
484
}
0 commit comments