Docx writer: handle table header using styles.

Instead of hard-coding the border and header cell vertical alignment,
we now let this be determined by the Table style, making use of
Word's "conditional formatting" for the table's first row.
For headerless tables, we use the tblLook element to tell Word
not to apply conditional first-row formatting.

Closes #7008.
This commit is contained in:
John MacFarlane 2021-01-12 09:49:10 -08:00
parent 4a223e68f4
commit c451207b08
34 changed files with 35 additions and 17 deletions

View file

@ -350,6 +350,21 @@
<w:right w:w="108" w:type="dxa" />
</w:tblCellMar>
</w:tblPr>
<w:tblStylePr w:type="firstRow">
<w:tblPr>
<w:jc w:val="left"/>
<w:tblInd w:w="0" w:type="dxa"/>
</w:tblPr>
<w:trPr>
<w:jc w:val="left"/>
</w:trPr>
<w:tcPr>
<w:vAlign w:val="bottom"/>
<w:tcBorders>
<w:bottom w:val="single"/>
</w:tcBorders>
</w:tcPr>
</w:tblStylePr>
</w:style>
<w:style w:type="paragraph" w:customStyle="1" w:styleId="DefinitionTerm">
<w:name w:val="Definition Term" />

View file

@ -1023,23 +1023,15 @@ blockToOpenXML' opts (Table _ blkCapt specs thead tbody tfoot) = do
_ -> es ++ [Elem $ mknode "w:p" [] ()]
headers' <- mapM cellToOpenXML $ zip aligns headers
rows' <- mapM (mapM cellToOpenXML . zip aligns) rows
let borderProps = Elem $ mknode "w:tcPr" []
[ mknode "w:tcBorders" []
$ mknode "w:bottom" [("w:val","single")] ()
, mknode "w:vAlign" [("w:val","bottom")] () ]
compactStyle <- pStyleM "Compact"
let emptyCell' = [Elem $ mknode "w:p" [] [mknode "w:pPr" [] [compactStyle]]]
let mkcell border contents = mknode "w:tc" []
$ [ borderProps | border ] ++
if null contents
then emptyCell'
else contents
let mkrow border cells =
let mkcell contents = mknode "w:tc" []
$ if null contents
then emptyCell'
else contents
let mkrow cells =
mknode "w:tr" [] $
[ mknode "w:trPr" []
[ mknode "w:cnfStyle" [("w:firstRow","1")] ()]
| border]
++ map (mkcell border) cells
map mkcell cells
let textwidth = 7920 -- 5.5 in in twips, 1/20 pt
let fullrow = 5000 -- 100% specified in pct
let rowwidth = fullrow * sum widths
@ -1047,6 +1039,15 @@ blockToOpenXML' opts (Table _ blkCapt specs thead tbody tfoot) = do
[("w:w", show (floor (textwidth * w) :: Integer))] ()
let hasHeader = not $ all null headers
modify $ \s -> s { stInTable = False }
-- for compatibility with Word <= 2007, we include a val with a bitmask
-- 0×0020 Apply first row conditional formatting
-- 0×0040 Apply last row conditional formatting
-- 0×0080 Apply first column conditional formatting
-- 0×0100 Apply last column conditional formatting
-- 0×0200 Do not apply row banding conditional formatting
-- 0×0400 Do not apply column banding conditional formattin
let tblLookVal :: Int
tblLookVal = if hasHeader then 0x20 else 0
return $
caption' ++
[Elem $
@ -1059,15 +1060,17 @@ blockToOpenXML' opts (Table _ blkCapt specs thead tbody tfoot) = do
,("w:firstColumn","0")
,("w:lastColumn","0")
,("w:noHBand","0")
,("w:noVBand","0")] () :
,("w:noVBand","0")
,("w:val", printf "%04x" tblLookVal)
] () :
[ mknode "w:tblCaption" [("w:val", T.unpack captionStr)] ()
| not (null caption) ] )
: mknode "w:tblGrid" []
(if all (==0) widths
then []
else map mkgridcol widths)
: [ mkrow True headers' | hasHeader ] ++
map (mkrow False) rows'
: [ mkrow headers' | hasHeader ] ++
map mkrow rows'
)]
blockToOpenXML' opts el
| BulletList lst <- el = addOpenXMLList BulletMarker lst

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.