Word agent
La classe WordAgent è un layer di manipolazione dei file .docx. Consente di leggere, modificare e creare documenti Word preservandone la struttura e la formattazione, operando tramite un formato strutturato condiviso (dizionari Python) per tutte le operazioni di lettura e scrittura.
Costruttore
WordAgent(file_bytes: bytes | None = None)
file_bytes(bytes | None): il contenuto binario del file.docx. SeNone, viene creato un documento vuoto.
Metodi
save
Restituisce il documento corrente come sequenza di bytes.
save() -> bytes
I bytes restituiti possono essere scritti direttamente su file o inviati all'utente come allegato.
get_structure
Restituisce una mappa testuale leggera dell'intero documento, preservando l'ordine reale di paragrafi, tabelle e immagini.
get_structure(preview_len: int = 40) -> str
preview_len(int): numero massimo di caratteri per le anteprime testuali.
L'output è una stringa con un formato simile a:
DOC STRUCTURE (12 elements)
────────────────────────────────────────────────────────────
[0 ] P Heading1: "Contratto di Fornitura" (22 chars)
[1 ] P Normal: (empty text, has embedded content)
└─ IMG inline | name="logo.png" | alt="Logo aziendale" | 5.2×2.1 cm | [rId7]
[2 ] P Heading2: "1. Premesse" (11 chars)
[3 ] P Normal: "La società Alfa S.r.l. con sede in via…" (142 chars)
[4 ] T Table 3×5
│ R0: Parentela | Codice Fiscale | Cognome e nome | Luogo nascita | Data nascita
│ R1: Moglie | RSSLRA75… | Rossi Laura | Ancona | 15/03/1975
│ R2: Figlio | RSSMRC05… | Rossi Marco | Ancona | 22/11/2005
[5 ] P Normal: "I prezzi si intendono IVA esclusa…" (87 chars)
[6…8 ] P (empty ×3)
[9 ] P Normal: "Firma _______________" (21 chars)
Le tabelle mostrano il contenuto di tutte le righe. I paragrafi vuoti consecutivi vengono collassati. Le immagini e le text box sono riportate come sotto-elementi del paragrafo che le contiene.
get
Restituisce la rappresentazione strutturata completa di un elemento per indice.
get(idx: int) -> dict
idx(int): indice dell'elemento nella mappa del documento.
Per i paragrafi il risultato ha questa forma:
{
"type": "paragraph",
"style": "Normal",
"alignment": "center", # opzionale
"runs": [
{"text": "Testo in grassetto ", "bold": True, "size_pt": 12.0, "font": "Calibri"},
{"text": "e testo normale"}
],
"images": [...], # opzionale, se presenti immagini ancorate
"textboxes": [...] # opzionale, se presenti text box
}
Per le tabelle il risultato ha questa forma:
{
"type": "table",
"rows": [
[
{"paragraphs": [{"type": "paragraph", "style": "Normal", "runs": [{"text": "Cella A1"}]}]},
{"paragraphs": [{"type": "paragraph", "style": "Normal", "runs": [{"text": "Cella B1"}]}]}
]
]
}
Le proprietà supportate nei run sono: text, bold, italic, underline, highlight, size_pt, font, color.
I run consecutivi con proprietà identiche vengono automaticamente compattati in un unico run per ridurre la dimensione dell'output.
get_table
Restituisce la rappresentazione strutturata di una tabella con metadati aggiuntivi.
get_table(idx: int) -> dict
idx(int): indice dell'elemento (deve essere una tabella).
Il risultato è identico a quello di get per le tabelle, con l'aggiunta di row_count e col_count.
Solleva TypeError se l'elemento indicato non è una tabella.
edit
Sovrascrive il contenuto di un elemento utilizzando un dizionario strutturato nello stesso formato restituito da get.
edit(idx: int, content: dict) -> None
idx(int): indice dell'elemento da modificare.content(dict): contenuto strutturato. Il campotypedeve corrispondere al tipo dell'elemento ("paragraph"o"table").
Il flusso tipico è: leggere con get, modificare il dizionario, riscrivere con edit.
Per le tabelle, se il dizionario contiene più righe di quelle esistenti, le righe aggiuntive vengono create automaticamente clonando la formattazione dall'ultima riga esistente.
edit_table_cell
Modifica il contenuto di una singola cella di una tabella.
edit_table_cell(idx: int, row: int, col: int, content: dict) -> None
idx(int): indice della tabella.row(int): indice di riga (0-based).col(int): indice di colonna (0-based).content(dict): contenuto della cella. Supporta due formati:- Shorthand:
{"text": "valore"}— modifica solo il testo preservando la formattazione esistente. - Completo:
{"paragraphs": [{"type": "paragraph", "style": "Normal", "runs": [...]}]}
- Shorthand:
edit_table_cells
Modifica più celle di una tabella in una singola chiamata.
edit_table_cells(idx: int, edits: list[dict]) -> None
idx(int): indice della tabella.edits(list): lista di dizionari, ciascuno conrow,colecontent(stesso formato diedit_table_cell).
add
Inserisce un nuovo elemento nel documento.
add(idx: int | None, content: dict) -> int
idx(int | None): posizione di inserimento. L'elemento viene inserito prima dell'indice specificato. SeNone, viene aggiunto in coda al documento.content(dict): contenuto strutturato (stesso formato diedit).
Restituisce l'indice dell'elemento appena inserito.
Dopo un add o un remove, gli indici degli elementi successivi cambiano. È necessario richiamare get_structure per ottenere gli indici aggiornati.
remove
Rimuove uno o più elementi dal documento per indice.
remove(ids: list[int]) -> None
ids(list[int]): lista degli indici da rimuovere.
Gli indici vengono processati in ordine decrescente internamente, quindi non è necessario preoccuparsi dello shift degli indici all'interno della stessa chiamata.
add_table_row
Aggiunge una riga a una tabella, ereditando la formattazione (bordi, font, dimensioni) da una riga esistente.
add_table_row(idx: int, after_row: int | None = None, values: list[str] | None = None) -> int
idx(int): indice della tabella.after_row(int | None): inserisce dopo questa riga.Noneaggiunge in coda.values(list[str] | None): valori testuali, uno per colonna.
Restituisce l'indice della nuova riga.
remove_table_row
Rimuove una riga da una tabella.
remove_table_row(idx: int, row: int) -> None
idx(int): indice della tabella.row(int): indice della riga da rimuovere (0-based).
add_table_col
Aggiunge una colonna a una tabella, ereditando la formattazione dalla colonna adiacente.
add_table_col(idx: int, after_col: int | None = None, header: str = "", default: str = "") -> int
idx(int): indice della tabella.after_col(int | None): inserisce dopo questa colonna.Noneaggiunge in coda.header(str): testo per la cella di intestazione (riga 0).default(str): testo predefinito per tutte le altre righe.
Restituisce l'indice della nuova colonna.
remove_table_col
Rimuove una colonna da una tabella.
remove_table_col(idx: int, col: int) -> None
idx(int): indice della tabella.col(int): indice della colonna da rimuovere (0-based).
search
Cerca un testo nell'intero documento (paragrafi e celle di tabella), con contesto circostante.
search(query: str, context_chars: int = 30) -> list[dict]
query(str): testo da cercare (case-insensitive).context_chars(int): numero di caratteri di contesto prima e dopo il match.
Restituisce una lista di dizionari:
[
{
"idx": 4,
"location": "P", # "P" per paragrafi, "T R1C2" per celle
"snippet": "…sottoscritto/a **Rossi** Lorenzo…"
}
]
La ricerca non richiede alcun LLM ed è eseguita direttamente sul documento.
get_image_bytes
Estrae i bytes di un'immagine dal documento tramite il suo relationship ID.
get_image_bytes(r_id: str) -> tuple[bytes, str]
r_id(str): il relationship ID dell'immagine (ottenibile daget_structureo daget).
Restituisce una tupla (image_bytes, format) dove format è una stringa come "png" o "jpg".
Solleva KeyError se il relationship ID non viene trovato nel documento.