Skip to content

Commit cab6ecd

Browse files
Benjamin-TBenjamin-T
authored andcommitted
Added code to work with captions and cross references
1 parent 94623ff commit cab6ecd

1 file changed

Lines changed: 330 additions & 0 deletions

File tree

docx/document.py

Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
from .enum.text import WD_BREAK
1414
from .section import Section, Sections
1515
from .shared import ElementProxy, Emu
16+
from .oxml.shared import qn
17+
from .oxml import CT_P
18+
from docx.oxml import OxmlElement
1619

1720

1821
class Document(ElementProxy):
@@ -61,7 +64,155 @@ def add_paragraph(self, text='', style=None):
6164
break.
6265
"""
6366
return self._body.add_paragraph(text, style)
67+
68+
def add_citation(self, bookmark, par=None):
69+
if par is not None:
70+
paragraph = par
71+
else:
72+
paragraph = self.add_paragraph()
73+
run = paragraph.add_run()
74+
fldChar = OxmlElement('w:fldChar') # creates a new element
75+
fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element
76+
77+
instrText = OxmlElement('w:instrText')
78+
instrText.set(qn('xml:space'), 'preserve') # sets attribute on element
79+
instrText.text = ' CITATION {:s} \l 1033'.format(bookmark)
80+
81+
fldChar2 = OxmlElement('w:fldChar')
82+
fldChar2.set(qn('w:fldCharType'), 'separate')
83+
fldChar3 = OxmlElement('w:t')
84+
fldChar3.text = "Right-click to update field."
85+
fldChar2.append(fldChar3)
86+
87+
fldChar4 = OxmlElement('w:fldChar')
88+
fldChar4.set(qn('w:fldCharType'), 'end')
89+
90+
r_element = run._r
91+
r_element.append(fldChar)
92+
r_element.append(instrText)
93+
r_element.append(fldChar2)
94+
r_element.append(fldChar4)
95+
p_element = paragraph._p
6496

97+
98+
def add_crossreference(self, bookmark, par=None, obj_type='figure'):
99+
# print('input', bookmark)
100+
# print('identifier', bookmark[:3])
101+
#
102+
if bookmark[:3] not in ['fig', 'tab', 'equ']:
103+
str_ = '{:s} is an incorrect bookmark, bookmark should start with fig, tab or equ'.format(bookmark)
104+
raise ValueError(str_)
105+
if par is not None:
106+
paragraph = par
107+
else:
108+
paragraph = self.add_paragraph()
109+
110+
fldChar = OxmlElement('w:fldChar') # creates a new element
111+
fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element
112+
113+
instrText = OxmlElement('w:instrText')
114+
instrText.set(qn('xml:space'), 'preserve')
115+
# sets attribute on element
116+
instrText.text = ' REF _Ref{:s} \# 0 \h'.format(bookmark)
117+
# instrText.text = ' REF {:s} \h'.format(bookmark)
118+
fldChar2 = OxmlElement('w:fldChar')
119+
fldChar2.set(qn('w:fldCharType'), 'separate')
120+
fldChar3 = OxmlElement('w:t')
121+
fldChar3.text = "1"
122+
# instrTextFig.append(fldChar3)
123+
124+
fldChar4 = OxmlElement('w:fldChar')
125+
fldChar4.set(qn('w:fldCharType'), 'end')
126+
127+
128+
run = paragraph.add_run()
129+
r_element = run._r
130+
fig = OxmlElement('w:t')
131+
fig.set(qn('xml:space'), 'preserve')
132+
133+
if bookmark[:3] == 'fig':
134+
fig.text = 'figure '
135+
if bookmark[:3] == 'tab':
136+
fig.text = 'table '
137+
if bookmark[:3] == 'equ':
138+
fig.text = 'equation '
139+
r_element.append(fig)
140+
141+
run = paragraph.add_run()
142+
r_element = run._r
143+
r_element.append(fldChar)
144+
145+
run = paragraph.add_run()
146+
r_element = run._r
147+
r_element.append(instrText)
148+
149+
run = paragraph.add_run()
150+
r_element = run._r
151+
r_element.append(fldChar2)
152+
153+
run = paragraph.add_run()
154+
r_element = run._r
155+
r_element.append(fldChar3)
156+
157+
run = paragraph.add_run()
158+
r_element = run._r
159+
r_element.append(fldChar4)
160+
p_element = paragraph._p
161+
162+
def create_caption(self, entry, paragraph, obj_type, bmark='1'):
163+
obj_type = obj_type.lower()
164+
run = paragraph.add_run()
165+
r = run._r
166+
167+
par = paragraph._p
168+
run = paragraph.add_run()
169+
r = run._r
170+
171+
bmrk = OxmlElement('w:bookmarkStart')
172+
bmrk.set(qn('w:id'), '1')
173+
bmrk.set(qn('w:name'), '_Ref{:s}'.format(bmark))
174+
par.append(bmrk)
175+
176+
fig = OxmlElement('w:t')
177+
fig.set(qn('xml:space'), 'preserve')
178+
if obj_type == 'figure':
179+
fig.text = 'Figure '
180+
if obj_type == 'table':
181+
fig.text = 'Table '
182+
r.append(fig)
183+
184+
fldChar_1 = OxmlElement('w:fldSimple')
185+
fldChar_1.set(qn('xml:space'), 'preserve')
186+
if obj_type == 'figure':
187+
fldChar_1.set(qn('w:instr'), ' SEQ Figure \* ARABIC ')
188+
if obj_type == 'table':
189+
fldChar_1.set(qn('w:instr'), ' SEQ Table \* ARABIC ')
190+
par.append(fldChar_1)
191+
192+
run = paragraph.add_run()
193+
r = run._r
194+
fldChar_2 = OxmlElement('w:fldChar')
195+
fldChar_2.set(qn('w:fldCharType'), "end")
196+
r.append(fldChar_2)
197+
198+
bmrk_1 = OxmlElement('w:bookmarkEnd')
199+
bmrk_1.set(qn('w:id'), '1')
200+
par.append(bmrk_1)
201+
202+
run = paragraph.add_run()
203+
caption = OxmlElement('w:t')
204+
caption.set(qn('xml:space'), 'preserve')
205+
caption.text = ' {:s}'.format(entry)
206+
run._r.append(caption)
207+
208+
def add_caption(self, caption, bmark, obj_type='figure'):
209+
"""
210+
211+
"""
212+
par = self.add_paragraph(style='caption')
213+
self.create_caption(caption, par, obj_type, bmark)
214+
return par
215+
65216
def add_picture(self, image_path_or_stream, width=None, height=None):
66217
"""
67218
Return a new picture shape added in its own paragraph at the end of
@@ -99,7 +250,186 @@ def add_table(self, rows, cols, style=None):
99250
table = self._body.add_table(rows, cols, self._block_width)
100251
table.style = style
101252
return table
253+
254+
def bookmark_text(self, bookmark_name, text, underline = False, italic = False, bold = False, style = None):
255+
doc_element = self._part._element
256+
bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart'))
257+
bookmarks_list = doc_element.findall('.//' + qn('wp:docPr'))
258+
for bookmark in bookmarks_list:
259+
name = bookmark.get(qn('wp:name'))
260+
print('asdf?', bookmark.name)
261+
if bookmark.name == bookmark_name:
262+
par = bookmark.getparent()
263+
264+
# if not isinstance(par, CT_P):
265+
# return False
266+
# else:
267+
print('test')
268+
i = par.index(bookmark) + 1
269+
print(i)
270+
p = self.add_paragraph()
271+
run = p.add_run(text, style)
272+
run.underline = underline
273+
run.italic = italic
274+
run.bold = bold
275+
par.insert(i, run._element)
276+
p = p._element
277+
p.getparent().remove(p)
278+
p._p = p._element = None
279+
return True
280+
return False
281+
282+
def bookmark_table(self, bookmark_name, rows, cols, style=None):
283+
tb = self.add_table(rows=rows, cols=cols, style=style)
284+
doc_element = self._part._element
285+
bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart'))
286+
for bookmark in bookmarks_list:
287+
name = bookmark.get(qn('w:name'))
288+
if name == bookmark_name:
289+
par = bookmark.getparent()
290+
if not isinstance(par, CT_P):
291+
return False
292+
else:
293+
i = par.index(bookmark) + 1
294+
par.addnext(tb._element)
295+
return tb
296+
return tb
297+
298+
def bookmark_picture(self, bookmark_name, picture, width=None, height=None, caption='', bmark=''):
299+
doc_element = self._part._element
300+
bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart'))
301+
for bookmark in bookmarks_list:
302+
name = bookmark.get(qn('w:name'))
303+
if name == bookmark_name:
304+
par = bookmark.getparent()
305+
if not isinstance(par, CT_P):
306+
return False
307+
else:
308+
i = par.index(bookmark) + 1
309+
p = self.add_paragraph()
310+
run = p.add_run()
311+
run.add_picture(picture, width, height)
312+
313+
# run.add_caption(caption, bmark)
314+
par.insert(i, run._element)
315+
p = p._element
316+
p.getparent().remove(p)
317+
p._p = None
318+
p._element = None
319+
return True
320+
321+
def delete_paragraph(self, paragraph):
322+
p = paragraph._element
323+
p.getparent().remove(p)
324+
p._p = p._element = None
325+
326+
327+
def add_table_of_contents(self):
328+
paragraph = self.add_paragraph()
329+
run = paragraph.add_run()
330+
fldChar = OxmlElement('w:fldChar') # creates a new element
331+
fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element
332+
instrText = OxmlElement('w:instrText')
333+
instrText.set(qn('xml:space'), 'preserve') # sets attribute on element
334+
instrText.text = r'TOC \o "1-3" \h \z \u' # change 1-3 depending on heading levels you need
335+
336+
fldChar2 = OxmlElement('w:fldChar')
337+
fldChar2.set(qn('w:fldCharType'), 'separate')
338+
fldChar3 = OxmlElement('w:t')
339+
fldChar3.text = "Right-click to update field."
340+
fldChar2.append(fldChar3)
341+
342+
fldChar4 = OxmlElement('w:fldChar')
343+
fldChar4.set(qn('w:fldCharType'), 'end')
344+
345+
r_element = run._r
346+
r_element.append(fldChar)
347+
r_element.append(instrText)
348+
r_element.append(fldChar2)
349+
r_element.append(fldChar4)
350+
p_element = paragraph._p
351+
352+
def add_bibliography(self):
353+
paragraph = self.add_paragraph()
354+
run = paragraph.add_run()
355+
fldChar = OxmlElement('w:fldChar') # creates a new element
356+
fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element
357+
instrText = OxmlElement('w:instrText')
358+
instrText.set(qn('xml:space'), 'preserve') # sets attribute on element
359+
instrText.text = r'BIBLIOGRAPHY' # change 1-3 depending on heading levels you need
360+
361+
fldChar2 = OxmlElement('w:fldChar')
362+
fldChar2.set(qn('w:fldCharType'), 'separate')
363+
fldChar3 = OxmlElement('w:t')
364+
fldChar3.text = "Right-click to update field."
365+
fldChar2.append(fldChar3)
366+
367+
fldChar4 = OxmlElement('w:fldChar')
368+
fldChar4.set(qn('w:fldCharType'), 'end')
369+
370+
r_element = run._r
371+
r_element.append(fldChar)
372+
r_element.append(instrText)
373+
r_element.append(fldChar2)
374+
r_element.append(fldChar4)
375+
p_element = paragraph._p
376+
377+
def remove_picture(self, bookmark_name):
378+
doc_element = self._part._element
379+
bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart'))
380+
for bookmark in bookmarks_list:
381+
name = bookmark.get(qn('w:name'))
382+
if name == bookmark_name:
383+
par = bookmark.getparent()
384+
102385

386+
# print(doc_element)
387+
if not isinstance(par, CT_P):
388+
return False
389+
else:
390+
i = par.index(bookmark) + 1
391+
p = self.add_paragraph()
392+
run = p.add_run()
393+
# run.add_picture(picture, width, height)
394+
395+
# run.add_caption(caption, bmark)
396+
par.insert(i, run._element)
397+
p = p._element
398+
p.getparent().remove(p)
399+
p._p = None
400+
p._element = None
401+
return True
402+
# def bookmark_picture(self, bookmark_name, picture):
403+
# doc_element = self._part._element
404+
# bookmarks_list = doc_element.findall('.//' + qn('wp:docPr'))
405+
# caption_list = doc_element.findall('.//' + qn('w:fldSimple'))
406+
## print(caption_list)
407+
# for bookmark in bookmarks_list:
408+
# name = bookmark.get(qn('wp:name'))
409+
## print('bmark_id', bookmark.id)
410+
## print('bmark_name', bookmark.name)
411+
# print(bookmark.name, bookmark_name)
412+
# if bookmark.name == bookmark_name:
413+
# print(bookmark.name)
414+
# par = bookmark.getparent()
415+
# print(par)
416+
#
417+
# test = _Body(par, CT_P())
418+
# #test.clear_content()
419+
#
420+
# run = test.add_paragraph().add_run()
421+
#
422+
#
423+
# run.add_picture(picture)
424+
#
425+
## if not isinstance(par, CT_P):
426+
## return False
427+
## else:
428+
# print('Doe iets')
429+
#
430+
# return True
431+
#
432+
103433
@property
104434
def core_properties(self):
105435
"""

0 commit comments

Comments
 (0)