A text box is a free-floating container in Word, often used for sidebars, callouts, label-style layouts, or holding images and tables at fixed positions. Unlike ordinary paragraphs, a text box can be positioned independently of the body text, giving you more layout flexibility. Inserting and styling them by hand is tedious, especially when a document needs many text boxes with a consistent look.
Python can insert and format text boxes in batch, place images and tables inside them, extract their text, and remove them as needed. This article demonstrates these common tasks using Spire.Doc for Python.
Setting Up the Environment
Install the Spire.Doc library:
pip install Spire.Doc
Then import the required modules in your script:
from spire.doc import *
from spire.doc.common import *
Inserting a Text Box and Setting Basic Styles
A text box is inserted through a paragraph's AppendTextBox() method, whose arguments are the width and height in points. After insertion, the Format property controls the border color, line style, and fill color, while Body holds the content inside the box:
document = Document()
section = document.AddSection()
paragraph = section.AddParagraph()
# Insert a 240x35 point text box
textBox = paragraph.AppendTextBox(240, 35)
# Set border and fill styles
textBox.Format.HorizontalAlignment = ShapeHorizontalAlignment.Left
textBox.Format.LineColor = Color.get_Gray()
textBox.Format.LineStyle = TextBoxLineStyle.Simple
textBox.Format.FillColor = Color.get_DarkSeaGreen()
# Add text inside the box and format it
para = textBox.Body.AddParagraph()
textRange = para.AppendText("First text box in the document")
textRange.CharacterFormat.FontName = "Lucida Sans Unicode"
textRange.CharacterFormat.FontSize = 14
textRange.CharacterFormat.TextColor = Color.get_White()
para.Format.HorizontalAlignment = HorizontalAlignment.Center
document.SaveToFile("textbox.docx", FileFormat.Docx)
document.Close()
TextBoxLineStyle offers several line styles (Simple, ThinThick, Triple, and more), while LineDashing controls solid and dashed lines (Solid, Dot, DashDotDot, and so on). Combining the two produces different border effects.
Controlling Position and Borders Precisely
By default a text box flows with the paragraphs. To pin it to a specific spot on the page, set a positioning origin and coordinates:
document = Document()
section = document.AddSection()
textBox = section.AddParagraph().AppendTextBox(310, 90)
# Add text inside the box
para = textBox.Body.AddParagraph()
textRange = para.AppendText("Spire.Doc offers a simple and effective method...")
textRange.CharacterFormat.FontSize = 13
# Position the box relative to the page
textBox.Format.HorizontalOrigin = HorizontalOrigin.Page
textBox.Format.HorizontalPosition = 120
textBox.Format.VerticalOrigin = VerticalOrigin.Page
textBox.Format.VerticalPosition = 100
# Set line style, color, and width
textBox.Format.LineStyle = TextBoxLineStyle.Double
textBox.Format.LineColor = Color.get_CornflowerBlue()
textBox.Format.LineDashing = LineDashing.Solid
textBox.Format.LineWidth = 5
# Set the internal margins
textBox.Format.InternalMargin.Top = 15
textBox.Format.InternalMargin.Bottom = 10
textBox.Format.InternalMargin.Left = 12
textBox.Format.InternalMargin.Right = 10
document.SaveToFile("textbox_format.docx", FileFormat.Docx)
document.Close()
HorizontalOrigin / VerticalOrigin set the coordinate reference (the page, here), and HorizontalPosition / VerticalPosition give the concrete coordinates. InternalMargin controls the spacing between text and border, each side individually.
Inserting an Image into a Text Box
A text box can hold more than text — you can also fill its background with an image:
document = Document()
section = document.AddSection()
textBox = section.AddParagraph().AppendTextBox(220, 220)
# Set the position
textBox.Format.HorizontalOrigin = HorizontalOrigin.Page
textBox.Format.HorizontalPosition = 50
textBox.Format.VerticalOrigin = VerticalOrigin.Page
textBox.Format.VerticalPosition = 50
# Fill the text box with a picture
textBox.Format.FillEfects.Type = BackgroundType.Picture
textBox.Format.FillEfects.SetPicture("logo.png")
document.SaveToFile("image_textbox.docx", FileFormat.Docx)
document.Close()
Setting FillEfects.Type to BackgroundType.Picture and calling FillEfects.SetPicture() fills the whole box with the image, effectively using it as the box's background.
Inserting a Table into a Text Box
A text box can also contain a table, which is useful for receipts and detail cards that need aligned content:
document = Document()
section = document.AddSection()
textBox = section.AddParagraph().AppendTextBox(300, 100)
textBox.Format.HorizontalOrigin = HorizontalOrigin.Page
textBox.Format.HorizontalPosition = 140
textBox.Format.VerticalOrigin = VerticalOrigin.Page
textBox.Format.VerticalPosition = 50
# Add a title inside the box
title = textBox.Body.AddParagraph().AppendText("Table 1")
# Add a table and define its size
table = textBox.Body.AddTable(True)
table.ResetCells(4, 4)
data = [
["Name", "Age", "Gender", "ID"],
["John", "28", "Male", "0023"],
["Steve", "30", "Male", "0024"],
["Lucy", "26", "Female", "0025"],
]
for i in range(4):
for j in range(4):
table.Rows[i].Cells[j].AddParagraph().AppendText(data[i][j])
# Apply a built-in table style
table.ApplyStyle(DefaultTableStyle.TableColorful2)
document.SaveToFile("table_textbox.docx", FileFormat.Docx)
document.Close()
Body.AddTable(True) creates a table inside the box, ResetCells() sets the row and column count, and ApplyStyle() applies a preset style. Cells are filled one by one just like a regular table.
Extracting Text from Text Boxes
The reverse operation is just as common: reading the contents of text boxes from an existing document. Text boxes live among a paragraph's child objects, so you need to traverse them level by level:
document = Document()
document.LoadFromFile("document_with_textboxes.docx")
if document.TextBoxes.Count > 0:
with open("extracted.txt", "w", encoding="utf-8") as f:
for i in range(document.Sections.Count):
section = document.Sections.get_Item(i)
for j in range(section.Paragraphs.Count):
paragraph = section.Paragraphs.get_Item(j)
for k in range(paragraph.ChildObjects.Count):
obj = paragraph.ChildObjects.get_Item(k)
if obj.DocumentObjectType == DocumentObjectType.TextBox:
textbox = obj
for x in range(textbox.ChildObjects.Count):
child = textbox.ChildObjects.get_Item(x)
if child.DocumentObjectType == DocumentObjectType.Paragraph:
f.write(child.Text)
elif child.DocumentObjectType == DocumentObjectType.Table:
table = child
for r in range(table.Rows.Count):
for c in range(table.Rows[r].Cells.Count):
for p in range(table.Rows[r].Cells[c].Paragraphs.Count):
f.write(table.Rows[r].Cells[c].Paragraphs.get_Item(p).Text)
document.Close()
The DocumentObjectType enum identifies each object: content inside a text box can be either a paragraph or a table, and the two must be handled separately. This logic can be used to batch-collect information scattered across many text boxes.
Removing a Text Box
Unwanted text boxes can be removed by index or cleared all at once:
document = Document()
document.LoadFromFile("template.docx")
# Remove the first text box
document.TextBoxes.RemoveAt(0)
# To clear all text boxes, use:
# document.TextBoxes.Clear()
document.SaveToFile("removed_textbox.docx", FileFormat.Docx)
document.Close()
The TextBoxes collection holds every text box in the document; RemoveAt() removes one by index, and Clear() removes them all.
Practical Tips
- Text box dimensions and coordinates are in points; one inch is about 72 points, so convert when needed.
- For fixed positioning, set
HorizontalOrigin/VerticalOrigintoPagebefore settingPosition, otherwise the coordinates may be computed against a different reference. - For CJK documents, specify a CJK font (such as
Microsoft YaHei) explicitly to avoid font fallback shifting the layout across machines. - Call
Close()when finished to release the file handle.
Conclusion
This article covered the full workflow of working with text boxes in Word using Python: inserting them with AppendTextBox(), styling and positioning them through the Format property, placing images and tables inside, extracting their contents by traversing DocumentObjectType, and removing them via the TextBoxes collection. With these techniques, you can hand tedious text box layout over to a script and keep your documents consistent and efficient.
Top comments (0)