En esta parte vamos a ver, de forma muy breve, cómo añadir cabeceros y pies de página. El resto de partes del tutorial las puedes encontrar en este enlace. Esta funcionalidad se ha añadido en la versión 0.8.8 de la biblioteca python-docx
y, de momento, estamos algo limitados en lo que se nos permite hacer.
Como siempre, vamos a empezar importando algunas bibliotecas:
1 2 3 4 |
import random import string from docx import Document |
Creamos un documento vacio:
1 |
doc = Document() |
Y lo rellenamos con 10 párrafos donde cada uno estará en una página ya que añadimos un salto de página después de cada párrafo.
1 2 3 4 |
for i in range(10): p = "".join([random.choice(string.ascii_letters) for _ in range(1000)]) doc.add_paragraph(p) doc.add_page_break() |
Si guardamos el documento:
1 |
doc.save("new.docx") |
Y lo abrimos con un procesador de textos, libreoffice en mi caso abierto desde un notebook o una consola IPython.
1 |
!libreoffice new.docx |
Veremos algo como lo siguiente:

Podemos abrir el mismo documento poniendo la ruta del fichero cuando instanciemos Document
:
1 |
doc = Document("new.docx") |
Podemos ver que es el mismo documento viendo, por ejemplo, que el número de párrafos que tenemos es 10:
1 2 |
paragraphs = doc.paragraphs print(len(paragraphs)) |
El resultado de la anterior nos mostrará ¿20
? en pantalla…
¡¡Uy!! Pero, ¿por qué hay 20 párrafos?
Si os acordáis, hace un momento hemos añadido 10 párrafos usando el método add_paragraph
. También hemos añadido 10 saltos de página usando el método add_page_break
. Este segundo método lo que hace es añadir un párrafo vacio que solo contiene un salto de página. Es por ello que tenemos 20 párrafos, los 10 con texto y otros 10 que contienen un salto de página.
Pero has dicho que íbamos a hablar de cabeceros y pies de página y todavía no has comentado nada…
Tranquilas, fieras.
Antes vamos a intentar a hablar un poco de lo que son las secciones.
Una sección vendría a ser una parte de un documento que comparte una serie de características como el ancho de página, la distancia del texto al borde superior, si las páginas estarán en vertical o en apaisado,…
Cuando creamos un documento de cero este dispone de una única sección:
1 2 3 4 |
sections = doc.sections print(len(sections)) section = sections[0] print(section) |
Lo anterior debería mostrar algo como:
1 2 |
1 <docx.section.Section object at 0x000001D58C62B888> |
Veamos todo lo que tienes disponible en este objeto:
1 |
print(dir(section)) |
Lo anterior mostrará:
1 2 3 4 5 6 7 8 9 10 11 |
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_document_part', '_sectPr', 'bottom_margin', 'different_first_page_header_footer', 'even_page_footer', 'even_page_header', 'first_page_footer', 'first_page_header', 'footer', 'footer_distance', 'gutter', 'header', 'header_distance', 'left_margin', 'orientation', 'page_height', 'page_width', 'right_margin', 'start_type', 'top_margin'] |
Vemos algunos nombres que podrían ser interesantes como:
different_first_page_header_footer
nos indica si la primera página, que solemos usar de portada del documento, tiene un cabecero y/o pie de página distinto al del resto del documento.first_page_header
yfirst_page_footer
sirven para que creemos el cabecero o pie de página, respectivamente, de la primera página y será visible sidifferent_first_page_header_footer
es igual aTrue
.Document.settings.odd_and_even_pages_header_footer
nos indica si el cabecero de las páginas pares y de las páginas impares debe ser diferente. Esto es una característica deSettings
y no deSection
.Settings
es un objeto al que podemos acceder a través de la propertysettings
de la instancia del objetoDocument
. Se hace de esta forma puesto que esto no se limita a una sección y lo definimos a nivel de documento.even_page_header
yeven_page_footer
sirven para que creemos el cabecero o pie de página, respectivamente, para las páginas pares y será visible y diferente al de las páginas impares siodd_and_even_pages_header_footer
es igual aTrue
.header
yfooter
sirven para marcar los cabeceros y/o pie de página de toda la sección. Se verán en unas páginas u otras dependiendo de los valores de todo lo que hemos indicado mas arriba,different_first_page_header_footer
,first_page_header
,first_page_footer
,odd_and_even_pages_header_footer
,even_page_header
yeven_page_footer
.
Vamos a juguetear un poco con todo esto a ver que sale. Primero vamos a acceder al primer párrafo y lo vamos a actualizar con algo que se parezca más a una portada.
1 2 |
par1 = doc.paragraphs[0] par1.text = "Texto para la primera página" |
Hemos actualizado el texto del primer párrafo usando el atributo text
Si volvemos a guardar el documento:
1 |
doc.save("new.docx") |
Deberíamos ver algo como lo siguiente en la primera página:

Ahora que ya tenemos una primera página que es un poco diferente del resto vamos a empezar a modificar cabeceros y pies de página.
1 2 3 4 |
header = section.header footer = section.footer header.add_paragraph("Esto es un cabecero general") footer.add_paragraph("Esto es un pie de página general") |
Usamos el método add_paragraph
para añadir texto al cabecero o pie de página. Vamos a volver a guardar el documento y ver cómo se ven nuestros flamantes cabeceros y pies de página:
1 |
doc.save("new.docx") |
Después de guardar, si lo volvemos a abrir con el procesador de texto que queráis podréis ver algo parecido a:

El cabecero y pie de página anterior se verá en todas las páginas del documento si lo dejamos tal cual. Normalmente, en la primera página, que suele ser la portada del documento, no queremos un cabecero o pie de página. Vamos a eliminarlos de la siguiente forma jugando con lo que hemos visto antes:
1 |
section.different_first_page_header_footer = True |
De esta forma nuestros cabecero y pie de página para la primera página lo podremos modificar usando section.first_page_header
y/o section.first_page_footer
. Si no modificamos los cabecero y pie de página de la primera página estarán vacios, que es lo que queríamos en un principio. Si queréis hacer otra cosa pues ya sabéis como hacerlo.
Como hemos hecho otras veces, podríais guardar el documento y visualizarlo como en anteriores ocasiones.
Si ahora queremos tener un cabecero para páginas pares y otro para páginas impares podemos hacer lo siguiente.
1 |
doc.settings.odd_and_even_pages_header_footer = True |
Vamos a definir los cabeceros para las páginas pares de nuestra sección:
1 2 |
section.even_page_header.add_paragraph("Cabecero en páginas pares") section.even_page_footer.add_paragraph("Pie de páginas en páginas pares") |
Por último, guardamos el documento y lo visualizamos con un procesador de texto.
1 |
doc.save("new.docx") |
En la imagen inferior podéis ver que el pie de página de la página par es de una forma mientras que el cabecero de la otra página, impar, es el cabecero general que definimos en un primer momento usando section.header
.

Resumiendo
Hemos visto como manejar cabeceros, pies de página y lo que es una sección. No hemos hecho cabeceros y pies de página muy sofisticados. Eso lo iremos viendo más tarde cuando aprendamos a formatear minimamente nuestro texto.
Hola!
Lo primero, muy buena pagina, me ha sido muy util. Se agradece el aporte.
Estoy intentando cambiar el estilo de un “header” desde python pero no lo he podido hacer. Tienes algunos consejos para hacerlo?
saludos!
Primero deberías ver los estilos que tienes disponibles para los headers. No hay mucho donde elegir, creo que son tres por defecto, header, header left y header right. Igual, si especificas un poco más qué quieres hacer es más fácil ayudarte. Quizá leer esto te ayude:
https://pybonacci.org/2020/06/30/escribiendo-ficheros-docx-de-word-con-python-capitulo-vii-estilos/
https://python-docx.readthedocs.io/en/latest/user/styles-understanding.html?highlight=styles