customize_footnote_style
Modify footnote numbering format, start number, font name, and font size in Word documents using direct customization options.
Instructions
Customize footnote numbering and formatting in a Word document.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filename | Yes | ||
| font_name | No | ||
| font_size | No | ||
| numbering_format | No | 1, 2, 3 | |
| start_number | No |
Implementation Reference
- The main asynchronous handler function implementing the tool logic: loads the DOCX document, handles input validation, customizes footnote style (font/size), finds references using helper, generates symbols, applies formatting via helper, and saves the document.async def customize_footnote_style(filename: str, numbering_format: str = "1, 2, 3", start_number: int = 1, font_name: Optional[str] = None, font_size: Optional[int] = None) -> str: """Customize footnote numbering and formatting in a Word document. Args: filename: Path to the Word document numbering_format: Format for footnote numbers (e.g., "1, 2, 3", "i, ii, iii", "a, b, c") start_number: Number to start footnote numbering from font_name: Optional font name for footnotes font_size: Optional font size for footnotes (in points) """ filename = ensure_docx_extension(filename) if not os.path.exists(filename): return f"Document {filename} does not exist" # Check if file is writeable is_writeable, error_message = check_file_writeable(filename) if not is_writeable: return f"Cannot modify document: {error_message}. Consider creating a copy first." try: doc = Document(filename) # Create or get footnote style footnote_style_name = "Footnote Text" footnote_style = None try: footnote_style = doc.styles[footnote_style_name] except KeyError: # Create the style if it doesn't exist footnote_style = doc.styles.add_style(footnote_style_name, WD_STYLE_TYPE.PARAGRAPH) # Apply formatting to footnote style if footnote_style: if font_name: footnote_style.font.name = font_name if font_size: footnote_style.font.size = Pt(font_size) # Find all existing footnote references footnote_refs = find_footnote_references(doc) # Generate format symbols for the specified numbering format format_symbols = get_format_symbols(numbering_format, len(footnote_refs) + start_number) # Apply custom formatting to footnotes count = customize_footnote_formatting(doc, footnote_refs, format_symbols, start_number, footnote_style) # Save the document doc.save(filename) return f"Footnote style and numbering customized in {filename}" except Exception as e: return f"Failed to customize footnote style: {str(e)}"
- word_document_server/tools/__init__.py:34-37 (registration)Tool registration via import into the tools package __init__.py, exposing customize_footnote_style for use in the MCP server alongside other footnote tools.from word_document_server.tools.footnote_tools import ( add_footnote_to_document, add_endnote_to_document, convert_footnotes_to_endnotes_in_document, customize_footnote_style )
- Core helper function called by the handler to update footnote reference symbols in the document text and reformat the footnote section with new symbols and applied style.def customize_footnote_formatting(doc, footnote_refs, format_symbols, start_number, style=None): """ Apply custom formatting to footnote references and text. Args: doc: Document object footnote_refs: List of footnote references from find_footnote_references() format_symbols: List of formatting symbols to use start_number: Number to start footnote numbering from style: Optional style to apply to footnote text Returns: Number of footnotes formatted """ # Update footnote references with new format for i, (para_idx, run_idx, _) in enumerate(footnote_refs): try: idx = i + start_number - 1 if idx < len(format_symbols): symbol = format_symbols[idx] else: symbol = str(idx + 1) # Fall back to numbers if we run out of symbols paragraph = doc.paragraphs[para_idx] paragraph.runs[run_idx].text = symbol except IndexError: # Skip if we can't locate the reference pass # Find footnote section and update found_footnote_section = False for para_idx, para in enumerate(doc.paragraphs): if para.text.startswith("Footnotes:") or para.text == "Footnotes": found_footnote_section = True # Update footnotes with new symbols for i in range(len(footnote_refs)): try: footnote_para_idx = para_idx + i + 1 if footnote_para_idx < len(doc.paragraphs): para = doc.paragraphs[footnote_para_idx] # Extract and preserve footnote text footnote_text = para.text if " " in footnote_text and len(footnote_text) > 2: # Remove the old footnote number/symbol footnote_text = footnote_text.split(" ", 1)[1] # Add new format idx = i + start_number - 1 if idx < len(format_symbols): symbol = format_symbols[idx] else: symbol = str(idx + 1) # Apply new formatting para.text = f"{symbol} {footnote_text}" # Apply style if style: para.style = style except IndexError: pass break return len(footnote_refs)
- Helper function used by the handler to locate all superscript numeric footnote references in the document paragraphs and runs.def find_footnote_references(doc) -> List[Tuple[int, int, str]]: """ Find all footnote references in a document. Args: doc: Document object Returns: List of tuples (paragraph_index, run_index, text) for each footnote reference """ footnote_references = [] for para_idx, para in enumerate(doc.paragraphs): for run_idx, run in enumerate(para.runs): if run.font.superscript and (run.text.isdigit() or run.text in "¹²³⁴⁵⁶⁷⁸⁹"): footnote_references.append((para_idx, run_idx, run.text)) return footnote_references
- Helper function used by the handler to generate the list of numbering symbols based on the provided format string (numeric, roman, alphabetic, symbols).def get_format_symbols(numbering_format: str, count: int) -> List[str]: """ Get a list of formatting symbols based on the specified numbering format. Args: numbering_format: Format for footnote/endnote numbers (e.g., "1, 2, 3", "i, ii, iii", "a, b, c") count: Number of symbols needed Returns: List of formatting symbols """ if numbering_format == "i, ii, iii": roman_numerals = ["i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii", "xiii", "xiv", "xv", "xvi", "xvii", "xviii", "xix", "xx"] return roman_numerals[:count] + [str(i) for i in range(count - len(roman_numerals) + 1, count + 1) if i > len(roman_numerals)] elif numbering_format == "a, b, c": alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] return alphabet[:count] + [str(i) for i in range(count - len(alphabet) + 1, count + 1) if i > len(alphabet)] elif numbering_format == "*, †, ‡": symbols = ["*", "†", "‡", "§", "¶", "||", "**", "††", "‡‡", "§§"] return symbols[:count] + [str(i) for i in range(count - len(symbols) + 1, count + 1) if i > len(symbols)] else: # Default to numbers return [str(i) for i in range(1, count + 1)]