使用Python-pptx复制幻灯片填充表格时遇索引越界错误求助
解决PPT表格数据填充时的
list index out of range错误 错误诊断
你的代码出现索引越界错误主要源于以下几个问题:
- 表格行索引超出实际行数:模板幻灯片表格只有9行,但
MAX_ROWS设为10,计算后的table_row_index会超过表格可用行数。 - 函数缩进错误:
parse_data函数内的format_text代码缩进错误,跑到函数外部,导致变量作用域混乱,table变量在函数内未定义。 - 幻灯片复制参数错误:调用
add_table_slide时传入slide对象,但函数定义要求传入幻灯片索引。 - slide_index递增逻辑错误:每次循环后无条件递增索引,导致后续访问
prs.slides[slide_index]时超出幻灯片列表长度。
修复方案
1. 匹配表格实际可填充行数
根据模板表格的总行数和表头偏移量,动态计算可填充的最大行数,避免硬编码:
# 从模板中获取表格总行数,减去表头行得到可用数据行 MAX_ROWS = len(template_table.rows) - OFFSET_ROW_INDEX
2. 修正parse_data函数的缩进与参数
将format_text代码移至函数内部,并传入table参数确保作用域正确:
def parse_data(table, sheet_data: SheetData, table_row_index: int, data_row_index: int) -> None: data1, data2, data3, data4, data5, data6, data7 = sheet_data format_text(table.cell(table_row_index, 0), data1[data_row_index]) format_text(table.cell(table_row_index, 1), data2[data_row_index]) format_text(table.cell(table_row_index, 2), data3[data_row_index]) format_text(table.cell(table_row_index, 3), data4[data_row_index]) format_text(table.cell(table_row_index, 4), data5[data_row_index]) format_text(table.cell(table_row_index, 5), data6[data_row_index]) format_text(table.cell(table_row_index, 6), data7[data_row_index])
3. 修复幻灯片复制的参数传递
调用add_table_slide时传入幻灯片索引而非对象:
if remaining_rows > 0: add_table_slide(prs, slide_index) slide_index += 1 start_row += fill_rows
4. 调整slide_index的递增逻辑
仅在必要时递增索引,避免越界:
while remaining_rows > 0: # 填充当前幻灯片逻辑... if remaining_rows > 0: add_table_slide(prs, slide_index) slide_index += 1 # 移到新创建的幻灯片 start_row += fill_rows else: slide_index += 1 # 没有剩余数据,移到下一个位置处理后续sheet
完整修正代码
import copy from pptx import Presentation from pptx.enum.shapes import MSO_SHAPE_TYPE from typing import List, Tuple SheetData = Tuple[List[str], List[str], List[str], List[str], List[str], List[str], List[str]] BLANK_SLIDE_LAYOUT_INDEX = 6 # 根据实际模板调整 OFFSET_ROW_INDEX = 1 # 表头占1行,数据从第2行开始(索引1) def format_text(cell, text): cell.text = text def add_table_slide(prs, index:int) -> None: source = prs.slides[index] duplicated_slide = prs.slides.add_slide(source.slide_layout) for shape in source.shapes: new_el = copy.deepcopy(shape.element) duplicated_slide.shapes._spTree.insert_element_before(new_el, 'p:extLst') def construct_pptx(template_dir: str, content: List[SheetData], output_dir: str) -> None: def parse_data(table, sheet_data: SheetData, table_row_index: int, data_row_index: int) -> None: data1, data2, data3, data4, data5, data6, data7 = sheet_data format_text(table.cell(table_row_index, 0), data1[data_row_index]) format_text(table.cell(table_row_index, 1), data2[data_row_index]) format_text(table.cell(table_row_index, 2), data3[data_row_index]) format_text(table.cell(table_row_index, 3), data4[data_row_index]) format_text(table.cell(table_row_index, 4), data5[data_row_index]) format_text(table.cell(table_row_index, 5), data6[data_row_index]) format_text(table.cell(table_row_index, 6), data7[data_row_index]) prs = Presentation(template_dir) # 获取模板表格信息 template_table = None for shape in prs.slides[0].shapes: if shape.shape_type == MSO_SHAPE_TYPE.TABLE: template_table = shape.table break if not template_table: raise ValueError("模板幻灯片中未找到表格") MAX_ROWS = len(template_table.rows) - OFFSET_ROW_INDEX slide_index = 0 for sheet_data in content: remaining_rows = len(sheet_data[0]) start_row = 0 while remaining_rows > 0: slide = prs.slides[slide_index] table = None for shape in slide.shapes: if shape.shape_type == MSO_SHAPE_TYPE.TABLE: table = shape.table break if not table: raise ValueError(f"幻灯片{slide_index}中未找到表格") fill_rows = min(MAX_ROWS, remaining_rows) for row_offset in range(fill_rows): data_row_index = start_row + row_offset table_row_index = OFFSET_ROW_INDEX + row_offset parse_data(table, sheet_data, table_row_index, data_row_index) remaining_rows -= 1 if remaining_rows > 0: add_table_slide(prs, slide_index) slide_index += 1 start_row += fill_rows else: slide_index += 1 prs.save(output_dir)
内容的提问来源于stack exchange,提问作者jenisdoe
相关产品推荐
相关产品推荐

