@@ -1037,6 +1037,86 @@ Base.@kwdef struct Footers
10371037 even:: Maybe{Footer} = nothing
10381038end
10391039
1040+ """
1041+ Column(; [width, space])
1042+
1043+ Describes a single column. `width` sets the column width, and `space` sets the whitespace after the column (before the next column).
1044+
1045+ See also: [`Columns`](@ref)
1046+ """
1047+ Base. @kwdef struct Column
1048+ width:: Maybe{Twip} = nothing
1049+ space:: Maybe{Twip} = nothing
1050+ end
1051+
1052+ """
1053+ Columns(; kwargs...)
1054+
1055+ Sets the columns for a [`Section`](@ref).
1056+
1057+ ## Keyword arguments
1058+
1059+ | Keyword | Description |
1060+ | :-- | :-- |
1061+ | `equal::Bool = true` | Sets all columns to be equal-width with `space` between every column |
1062+ | `num::Int` | The number of columns to layout. Ignored if `equal==false`. |
1063+ | `space::`[`Twip`](@ref) | The space between columns. Ignored if `equal==false`. |
1064+ | `sep::Bool = false` | Sets whether a vertical separator line is drawn between columns |
1065+ | `cols::Vector{`[`Column`](@ref)`}` | A vector of custom columns. May not be specified with `equal==true`. |
1066+ """
1067+ struct Columns
1068+ num:: Int
1069+ space:: Maybe{Twip}
1070+ sep:: Bool
1071+ cols:: Vector{Column}
1072+ equal:: Bool
1073+
1074+ function Columns (;kwargs... )
1075+ sd = setdiff (keys (kwargs), (:num , :space , :sep , :cols , :equal ))
1076+ isempty (sd) || throw (ArgumentError (" got unsupported keyword argument(s): $(sd) " ))
1077+ if haskey (kwargs, :cols ) && haskey (kwargs, :equal ) && kwargs[:equal ]
1078+ throw (ArgumentError (" keyword arguments \" cols\" and \" equal\" (or equal=true) are mutually incompatible. If \" cols\" is given, \" equal\" must be false or not defined" ))
1079+ elseif ! haskey (kwargs, :cols ) && haskey (kwargs, :equal ) && ! kwargs[:equal ]
1080+ throw (ArgumentError (" \" cols\" must be defined/non-empty when \" equal=false\" " ))
1081+ end
1082+ haskey (kwargs, :cols ) && isempty (kwargs[:cols ]) && throw (ArgumentError (" \" cols\" must not be empty" ))
1083+
1084+ return new (
1085+ get (kwargs, :num , 1 ),
1086+ get (kwargs, :space , nothing ),
1087+ get (kwargs, :sep , false ),
1088+ get (kwargs, :cols , Column[]),
1089+ get (kwargs, :equal , ! haskey (kwargs, :cols )))
1090+ end
1091+ end
1092+
1093+ """
1094+ PageMargins(; top, right, bottom, left, kwargs...)
1095+
1096+ Describes page margins in a [`Section`](@ref).
1097+
1098+ ## Keyword arguments
1099+
1100+ | Keyword | Description |
1101+ | :-- | :-- |
1102+ | `top::`[`Twip`](@ref) | The top margin. |
1103+ | `right::`[`Twip`](@ref) | The right margin. |
1104+ | `bottom::`[`Twip`](@ref) | The bottom margin. |
1105+ | `left::`[`Twip`](@ref) | The left margin. |
1106+ | `header::`[`Twip`](@ref)`=Twip(0)` | The header margin. |
1107+ | `footer::`[`Twip`](@ref)`=Twip(0)` | The footer margin. |
1108+ | `gutter::`[`Twip`](@ref)`=Twip(0)` | The gutter margin. |
1109+ """
1110+ Base. @kwdef struct PageMargins
1111+ top:: Twip
1112+ right:: Twip
1113+ bottom:: Twip
1114+ left:: Twip
1115+ header:: Twip = Twip (0 )
1116+ footer:: Twip = Twip (0 )
1117+ gutter:: Twip = Twip (0 )
1118+ end
1119+
10401120"""
10411121 SectionProperties(; kwargs...)
10421122
@@ -1047,15 +1127,19 @@ Holds properties for a [`Section`](@ref).
10471127| Keyword | Description |
10481128| :-- | :-- |
10491129| `pagesize::PageSize` | The size of each page in the section. |
1130+ | `margins::PageMargins` | The margins for each page in the section |
10501131| `valign::PageVerticalAlign.T` | The vertical alignment of content on each page of the section. |
10511132| `headers::`[`Headers`](@ref) | Defines the header content shown at the top of each page of the section. |
10521133| `footers::`[`Footers`](@ref) | Defines the footer content shown at the bottom of each page of the section. |
1134+ | `columns::`[`Columns`](@ref) | Configures the columns in the section |
10531135"""
10541136Base. @kwdef struct SectionProperties
10551137 pagesize:: Maybe{PageSize} = nothing
1138+ margins:: Maybe{PageMargins} = nothing
10561139 valign:: Maybe{PageVerticalAlign.T} = nothing
10571140 headers:: Maybe{Headers} = nothing
10581141 footers:: Maybe{Footers} = nothing
1142+ columns:: Maybe{Columns} = nothing
10591143end
10601144
10611145"""
@@ -1590,9 +1674,15 @@ function to_xml(body::Body, rels)
15901674 if props. pagesize != = nothing
15911675 E. link! (section_params_node, to_xml (props. pagesize, rels))
15921676 end
1677+ if props. margins != = nothing
1678+ E. link! (section_params_node, to_xml (props. margins, rels))
1679+ end
15931680 if props. valign != = nothing
15941681 E. link! (section_params_node, to_xml (props. valign, rels))
15951682 end
1683+ if props. columns != = nothing
1684+ E. link! (section_params_node, to_xml (props. columns, rels))
1685+ end
15961686 if props. headers != = nothing
15971687 for type in (:default , :first , :even )
15981688 x = getproperty (props. headers, type)
@@ -1827,6 +1917,14 @@ function children(p::ParagraphProperties)
18271917 return c
18281918end
18291919
1920+ function children (p:: Columns )
1921+ c = []
1922+ if ! p. equal
1923+ append! (c, p. cols)
1924+ end
1925+ return c
1926+ end
1927+
18301928function children (p:: TableCellProperties )
18311929 c = []
18321930 p. borders === nothing || push! (c, p. borders)
@@ -1899,6 +1997,7 @@ function attributes(t::Union{TableCellBorder, ParagraphBorder})
18991997 return attrs
19001998end
19011999attributes (p:: PageSize ) = ((" w:h" , p. height), (" w:w" , p. width), (" w:orient" , p. orientation))
2000+ attributes (p:: PageMargins ) = ((" w:top" , p. top), (" w:right" , p. right), (" w:bottom" , p. bottom), (" w:left" , p. left), (" w:header" , p. header), (" w:footer" , p. footer), (" w:gutter" , p. gutter))
19022001attributes (p:: PageVerticalAlign.T ) = ((" w:val" , p),)
19032002attributes (p:: Justification.T ) = ((" w:val" , p),)
19042003function attributes (s:: Style )
@@ -1915,6 +2014,26 @@ end
19152014attributes (p:: ParagraphStyle ) = ((" w:val" , p. name),)
19162015attributes (p:: RunStyle ) = ((" w:val" , p. name),)
19172016attributes (p:: VerticalAlignment.T ) = ((" w:val" , p),)
2017+ function attributes (p:: Column )
2018+ attrs = Tuple{String, Any}[]
2019+ p. width === nothing || push! (attrs, (" w:w" , p. width))
2020+ p. space === nothing || push! (attrs, (" w:space" , p. space))
2021+ return attrs
2022+ end
2023+ function attributes (p:: Columns )
2024+ attrs = Tuple{String, Any}[]
2025+ if p. num > 1 && p. equal
2026+ push! (attrs, (" w:equalWidth" , p. equal))
2027+ push! (attrs, (" w:num" , p. num))
2028+ p. sep === false || push! (attrs, (" w:sep" , p. sep))
2029+ p. space === nothing || push! (attrs, (" w:space" , p. space))
2030+ elseif ! p. equal
2031+ push! (attrs, (" w:equalWidth" , p. equal))
2032+ push! (attrs, (" w:num" , length (p. cols)))
2033+ p. sep === false || push! (attrs, (" w:sep" , p. sep))
2034+ end
2035+ return attrs
2036+ end
19182037function attributes (f:: Fonts )
19192038 attrs = Tuple{String, Any}[]
19202039 f. ascii === nothing || push! (attrs, (" w:ascii" , f. ascii))
@@ -2011,7 +2130,10 @@ function xmltag(t::Tuple{ParagraphBorder, Symbol})
20112130 throw (ArgumentError (" Invalid symbol $(repr (sym)) , options are :top, :left, :right, :bottom, :between." ))
20122131end
20132132xmltag (:: PageSize ) = " w:pgSz"
2133+ xmltag (:: PageMargins ) = " w:pgMar"
20142134xmltag (:: PageVerticalAlign.T ) = " w:vAlign"
2135+ xmltag (:: Columns ) = " w:cols"
2136+ xmltag (:: Column ) = " w:col"
20152137xmltag (:: Style ) = " w:style"
20162138xmltag (:: Justification.T ) = " w:jc"
20172139xmltag (:: Fonts ) = " w:rFonts"
0 commit comments