Я пытаюсь найти и заменить, используя python-docx.
Я использую этот код, разработанный adejones: Как искать и заменять слово/текст в документе Word с помощью Python-docx
Я использовал этот код для небольших документов, но текущий документ, который я использую, довольно большой (со многими таблицами), поэтому я пытаюсь решить, что вызывает «индекс списка выходит за пределы диапазона». После долгих отладок я понял, что это происходит при работе с таблицей, в которой много объединенных ячеек, примерно так:
Ошибка возникает в «для ячейки в row.cells». С помощью отладчика я определил, что у t.rows есть объект, а у строки есть объект, поэтому все, что происходит до получения одной из ячеек, работает.
К сожалению, я не могу поделиться этим документом, но любопытно, есть ли у кого-нибудь идеи, как преодолеть это препятствие.
Ошибка:
File "C:\Anaconda3\lib\site-packages\docx\table.py", line 161, in _cells
cells.append(cells[-col_count])
IndexError: list index out of range
Код:
def docx_find_replace_text(doc, search_text, replace_text):
paragraphs = list(doc.paragraphs)
for t in doc.tables:
for row in t.rows:
for cell in row.cells:
for paragraph in cell.paragraphs:
paragraphs.append(paragraph)
for p in paragraphs:
if search_text in p.text:
inline = p.runs
# Replace strings and retain the same style.
# The text to be replaced can be split over several runs so
# search through, identify which runs need to have text replaced
# then replace the text in those identified
started = False
search_index = 0
# found_runs is a list of (inline index, index of match, length of match)
found_runs = list()
found_all = False
replace_done = False
for i in range(len(inline)):
# case 1: found in single run so short circuit the replace
if search_text in inline[i].text and not started:
found_runs.append((i, inline[i].text.find(search_text), len(search_text)))
text = inline[i].text.replace(search_text, str(replace_text))
inline[i].text = text
replace_done = True
found_all = True
break
if search_text[search_index] not in inline[i].text and not started:
# keep looking ...
continue
# case 2: search for partial text, find first run
if search_text[search_index] in inline[i].text and inline[i].text[-1] in search_text and not started:
# check sequence
start_index = inline[i].text.find(search_text[search_index])
check_length = len(inline[i].text)
for text_index in range(start_index, check_length):
if inline[i].text[text_index] != search_text[search_index]:
# no match so must be false positive
break
if search_index == 0:
started = True
chars_found = check_length - start_index
search_index += chars_found
found_runs.append((i, start_index, chars_found))
if search_index != len(search_text):
continue
else:
# found all chars in search_text
found_all = True
break
# case 2: search for partial text, find subsequent run
if search_text[search_index] in inline[i].text and started and not found_all:
# check sequence
chars_found = 0
check_length = len(inline[i].text)
for text_index in range(0, check_length):
if inline[i].text[text_index] == search_text[search_index]:
search_index += 1
chars_found += 1
else:
break
# no match so must be end
found_runs.append((i, 0, chars_found))
if search_index == len(search_text):
found_all = True
break
if found_all and not replace_done:
for i, item in enumerate(found_runs):
index, start, length = [t for t in item]
if i == 0:
text = inline[index].text.replace(inline[index].text[start:start + length], str(replace_text))
inline[index].text = text
else:
text = inline[index].text.replace(inline[index].text[start:start + length], '')
inline[index].text = text
Кажется, я нашел ответ.
При переборе таблиц, а точнее строк, docx не любит объединенные строки. Объединенные столбцы допустимы, поскольку они могут быть частью строки. Однако если объединено более двух строк, неизвестно, как анализировать оставшиеся столбцы. См. изображение ниже. Я не уверен, почему одно слияние допустимо, а несколько объединенных строк — нет. Как только я удалил объединенные строки из своих таблиц, код заработал.
Ваш ответ можно улучшить, добавив дополнительную вспомогательную информацию. Пожалуйста, отредактируйте , добавив дополнительную информацию, например цитаты или документацию, чтобы другие могли подтвердить правильность вашего ответа. Более подробную информацию о том, как писать хорошие ответы, вы можете найти в справочном центре.