Skip to content

Commit 34d1c51

Browse files
author
Steve Canny
committed
spike: experiment with headers
1 parent ff81d3e commit 34d1c51

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
2+
Headers experimentation
3+
=======================
4+
5+
Notes
6+
-----
7+
8+
* If Header inherits from docx.blkcntnr.BlockItemContainer (as does
9+
docx.document._Body), we get the content editing for free (add_paragraph(),
10+
.paragraphs, .tables, etc.). We'll need to take a closer look to make sure,
11+
but I'm thinking it should work unchanged.
12+
13+
14+
Header API
15+
----------
16+
17+
* Header.is_linked_to_previous - read/write boolean, behavior outlined below.
18+
19+
* Header.text - read/write, full text, no character formatting, \n for line
20+
break, \n\n for paragraph (or whatever other .text bits do). Assignment can
21+
only be a single paragraph; can include tabs and line breaks, but no
22+
paragraphs.
23+
24+
* Items inherited from BlockItemContainer (.paragraphs, .tables,
25+
.add_paragraph(), .add_table())
26+
27+
28+
Operations to be supported
29+
--------------------------
30+
31+
* Detect whether header is present or inherited (linked to previous)
32+
* Create header when there is none
33+
* Obtain reference to effective header content
34+
* Remove header, making it inherited (linked to previous)
35+
36+
Protocol candidate::
37+
38+
# every section has a header; it is never None
39+
40+
>>> header = section.header
41+
>>> header
42+
<docx.hdrftr.Header object at 0x02468ACE>
43+
44+
# if that section has no w:headerReference, it inherits from the prior
45+
# section
46+
47+
>>> header.is_linked_to_previous
48+
True
49+
50+
# constructive editing operations transparently operate on the source
51+
# header, that of the first prior section having a header (if the current
52+
# section has none). If no prior sections have a header, one is created
53+
# in the first section of the document on the first constructive edit
54+
# call.
55+
56+
>>> header = document.sections[0].header
57+
>>> header.is_linked_to_previous
58+
True
59+
>>> header.text = 'foobar'
60+
>>> header.is_linked_to_previous
61+
False
62+
63+
# A header can be explicitly added to a section by assigning False to
64+
# Header.is_linked_to_previous
65+
66+
>>> header.is_linked_to_previous
67+
True
68+
>>> header.is_linked_to_previous = False
69+
>>> header.is_linked_to_previous
70+
False
71+
72+
# Conversely, a header can be deleted from a section by assigning True to
73+
# Header.is_linked_to_previous
74+
75+
>>> header.is_linked_to_previous
76+
False
77+
>>> header.is_linked_to_previous = True
78+
>>> header.is_linked_to_previous
79+
True
80+
81+
82+
Use cases
83+
---------
84+
85+
* Add a header to a single section document::
86+
87+
>>> header = document.sections[0].header
88+
>>> header.text = 'foobar'
89+
90+
* Get the header text from a single section document::
91+
92+
>>> header = document.sections[0].header
93+
>>> header.text
94+
'foobar'
95+
96+
* Insert a section in the middle of (above) a single section that has
97+
a header defined.
98+
99+
100+
Conclusions
101+
-----------
102+
103+
* An empty header is NOT the same as no header. Word saves an empty header
104+
when necessary to make a section's header distinct from that of the prior
105+
section. This is accomplished in the UI by unchecking the 'Link to
106+
Previous' checkbox. The absence of a header indicates its value is
107+
inherited. An empty header just displays no content, but is in every other
108+
way a full header.
109+
110+
* A header part never exists without at least one w:headerReference element
111+
pointing to it. The associated header part needs to be removed when
112+
a w:headerReference element is removed.
113+
114+
* A first and even header reference and part are retained even when they are
115+
"hidden" by the "different first page" or "even and odd" settings for the
116+
document.
117+
118+
* A header can only be inherited from (linked to) the immediately prior
119+
section. If the prior header is itself inherited, the inheritance is
120+
cascaded. Inheritance cannot "skip over" an intervening header; Only the
121+
first prior header is available for inheritance.
122+
123+
124+
Experiment agenda
125+
-----------------
126+
127+
* [ ] Create three-section document with no headers. Add header to each
128+
section separately and see what happens in each case. Start fresh for
129+
each case.
130+
131+
* [ ] Create single section document, give it a header, then insert second
132+
section in the middle. Who gets the header and who inherits (or gets
133+
copies)?
134+
135+
* [ ] Create document with even-odd headers and three sections. See if headers
136+
can be inherited separately or needs to be all three at once (in UI
137+
anyway).
138+
139+
* [ ] Can a header part be referred to by multiple references? (I'm thinking
140+
no, based on inheritance can't skip a section.) Might need to try this
141+
with manual editing to see if Word barfs. I'm not seeing just now how
142+
this might reasonably arise, except maybe inserting a section between
143+
two that inherit and changing the new section's header
144+
145+
146+
Experiment 1 - View header/footer
147+
---------------------------------
148+
149+
* A blank document has a sectPr, but it contains no header or footer
150+
references. The document contains no header or footer parts.
151+
152+
* `View > Header and Footer` displays a header and footer editing area and
153+
places the insertion point within.
154+
155+
* Entering the area but not making a change, does not create a header.
156+
157+
* Entering the area and adding text, creates a header. The header
158+
contents are displayed in a grayed out font after leaving the header
159+
editing area.
160+
161+
* Deleting the entire contents of the header (but leaving the non-deletable
162+
paragraph mark) removes the header part and reference.
163+
164+
165+
Experiment 2 - Add section
166+
--------------------------
167+
168+
* Inserting a section break in the middle of a single section document having
169+
no header adds a new w:sectPr at the insertion point. The new section has
170+
no header references.
171+
172+
* After adding a header only to the first section:
173+
174+
+ A w:headerReference is added to the first w:sectPr
175+
+ No w:headerReference is added to the second w:sectPr
176+
+ The 'Link to Previous' checkbox is ticked on the Header toolbar for the
177+
second section.
178+
+ The section 1 header is displayed on the second section in the UI; the
179+
header info/control bar displays 'Same as Previous'.
180+
181+
* Adding a header only to the second section has two variants:
182+
183+
+ In the default case, the 'Link to Previous' checkbox is checked (for the
184+
second section) by default when the new section is inserted.
185+
186+
In this case, a w:headerReference element is added to the *first*
187+
w:sectPr and is inherited by the second section, even though the editing
188+
is done on the section section editing area.
189+
190+
+ The second case requires clearing the 'Link to Previous' checkbox.
191+
192+
In this case, a w:headerReference is added to the second section only.
193+
Only the one header part is added.
194+
195+
196+
Anomalies
197+
---------
198+
199+
* Something odd happens when unlinking then relinking the second header. The
200+
first section gets all three header and footerReference elements and six
201+
new parts are added (3 each header and footer).
202+
203+
204+
Common experiment steps
205+
-----------------------
206+
207+
1. Create new document, change page setup to A5 landscape (so multiple pages
208+
show easily at once).
209+
210+
2. Type in 'Section 1<CR>Section 2'. Insert a section break (next page)
211+
before the 'S' beginning the second paragraph.
212+
213+
3. Enter header edit mode using View > Header and Footer
25.7 KB
Binary file not shown.

0 commit comments

Comments
 (0)