-
Notifications
You must be signed in to change notification settings - Fork 425
Open
Labels
Description
Describe the bug
When using docxtpl.DocxTemplate to generate a Word document containing multiple embedded Excel files through sub-documents, only the first embedded Excel object can be opened normally.
All others appear visually correct but cannot be opened (no response when double-clicked), and the context menu lacks the “Worksheet Object” option.
To Reproduce
import os
import openpyxl
from docxtpl import DocxTemplate
class ExcelOperator(object):
def __init__(self, excel_file_path):
self.excel_file_path = excel_file_path
self.headers = ["Column1", "Column2", "Column3", "Column4", "Column5"]
def _create_excel(self):
wb = openpyxl.Workbook()
ws = wb.active
ws.append(self.headers)
return wb, ws
def write_excel(self, data, sheet_name="DataSheet"):
work_book, work_sheet = self._create_excel()
work_sheet.title = sheet_name
for item in data:
work_sheet.append(item)
work_book.save(self.excel_file_path)
class WordOperator(object):
def __init__(self, main_tpl_file_path, sub_tpl_file_path, output_file_path):
self.current_path = os.path.dirname(os.path.abspath(__file__))
self.main_tpl_file_path = main_tpl_file_path
self.sub_tpl_file_path = sub_tpl_file_path
self.output_file_path = output_file_path
def _build_sub_excel_docx(self, index, item_data):
# Generate Excel data file
excel_file_path = os.path.join(self.current_path, f"output/0.tmp_excel_{index}.xlsx")
excel_operator = ExcelOperator(excel_file_path)
excel_operator.write_excel(item_data["data"], item_data["name"])
sub_docx_file_path = os.path.join(self.current_path, f"output/0.tmp_sub_doc_{index}.docx")
# Load sub template file and replace the embedded Excel file with the newly generated Excel data file
sub_docx = DocxTemplate(self.sub_tpl_file_path)
sub_docx.replace_zipname('word/embeddings/Microsoft_Excel_Worksheet.xlsx', excel_file_path)
sub_docx.save(sub_docx_file_path)
return sub_docx_file_path
def write_word(self, data_list):
# Create main template file
main_ctx = {
"sub_docs": []
}
main_docx = DocxTemplate(self.main_tpl_file_path)
# Cycle through data list to create sub documents
for index, item in enumerate(data_list):
# build sub document with embedded Excel
sub_docx_file_path = self._build_sub_excel_docx(index, item)
# load sub document into main document context
sub_doc_tpl = main_docx.new_subdoc(sub_docx_file_path)
main_ctx["sub_docs"].append(sub_doc_tpl)
# Render and save main document
main_docx.render(main_ctx)
main_docx.save(self.output_file_path)
if __name__ == "__main__":
data_list = [
{"name": "No.1", "data": [["1-1", "1-2", "1-3", "1-4", "1-5"]]},
{"name": "No.2", "data": [["2-1", "2-2", "2-3", "2-4", "2-5"]]},
{"name": "No.3", "data": [["3-1", "3-2", "3-3", "3-4", "3-5"]]},
{"name": "No.4", "data": [["4-1", "4-2", "4-3", "4-4", "4-5"]]},
{"name": "No.5", "data": [["5-1", "5-2", "5-3", "5-4", "5-5"]]},
{"name": "No.6", "data": [["6-1", "6-2", "6-3", "6-4", "6-5"]]},
{"name": "No.7", "data": [["7-1", "7-2", "7-3", "7-4", "7-5"]]}
]
current_path = os.path.dirname(os.path.abspath(__file__))
# Generate Word document with embedded Excel files
main_template_file_path = os.path.join(current_path, f"templates/tpl_demo_doc_main_v3.docx")
sub_template_file_path = os.path.join(current_path, f"templates/tpl_demo_doc_sub_excel.docx")
result_file_path = os.path.join(current_path, f"output/demo_doc_with_excel.docx")
word_operator = WordOperator(main_template_file_path, sub_template_file_path, result_file_path)
word_operator.write_word(data_list)
Expected behavior
All embedded Excel objects should behave like the first one — openable by double-click and recognized as valid “Worksheet Object” embeddings.
Screenshots
Additional context
- The generated main document contains 7 embedded Excel icons (verified inside the .docx archive at word/embeddings/):
Microsoft_Excel_Worksheet1.xlsx
Microsoft_Excel_Worksheet2.xlsx
Microsoft_Excel_Worksheet3.xlsx
Microsoft_Excel_Worksheet4.xlsx
Microsoft_Excel_Worksheet5.xlsx
Microsoft_Excel_Worksheet6.xlsx
Microsoft_Excel_Worksheet7.xlsx - All 7 .xlsx files in the word/embeddings/ folder are valid and open normally if extracted.
- However:
- Only the first embedded Excel object inside the final .docx opens correctly when double-clicked.
- The rest cannot be opened and show no context menu entry for “Worksheet Object”.
- See the compressed package for code and running result files docx_demo_v2.tar.gz
Environment
Python 3.11.3
docxtpl 0.20.1
python-docx 1.2.0
openpyxl 3.1.2