XLSX с репликами в CSV через Python: проверка текстовых ячеек и формул
Выгрузка одного согласованного листа через openpyxl. Сохранение текстовых ID и таймкодов, остановка на формулах и проверка результата через csv.reader.
Определите границы выгрузки
Задача возникает, когда редактор проверил реплики в таблице, а следующему инструменту нужен простой CSV. Это обратное направление по отношению к загрузке CSV в Excel: вы переносите значения одного листа, а не форматированный документ целиком.
Используйте копию книги с листом Replicas и колонками replica_id, speaker, timecode, text в этом порядке. Каждая строка соответствует одной реплике. Не добавляйте в этот лист сводные итоги, заголовки разделов и дополнительные заметки: их роль нельзя угадать из внешнего вида ячейки.
Если исходная расшифровка ещё не подготовлена, получите текстовую основу через Транскрибатор, затем сформируйте и проверьте таблицу самостоятельно. Пример не предполагает наличие готового экспорта XLSX в сервисе.
Проверьте значения, а не отображение
В Excel значение и способ его отображения могут различаться. Число 1 с форматом 000 выглядит как 001, но чтение значения вернёт число. Время также может быть числовым или объектом даты. Не превращайте такие ячейки в строки автоматически: это создаст другую запись, а не сохранит видимый таймкод.
В рабочей копии заранее задайте явные текстовые ID и таймкоды, сверив их с источником. Для предотвращения этой проблемы при первоначальном импорте полезна инструкция по текстовым таймкодам в Excel. Изменение формата уже испорченной ячейки само по себе не возвращает исходное представление.
Формулы требуют отдельного решения. Код ниже открывает книгу с data_only=False и прекращает выгрузку при формуле. Он не вычисляет Excel-формулы и не выдаёт сохранённый кэш за актуальный результат. Сначала подготовьте согласованные значения и проверьте их вручную.
Запустите строгую выгрузку
Понадобятся Python и библиотека openpyxl. В своём окружении установите её из обычного пакета командой python -m pip install openpyxl. Сохраните скрипт рядом с рабочей копией interview.xlsx. Если лист называется иначе, замените его имя явно.
Скрипт сначала проверяет все строки и только потом создаёт CSV. Полностью пустые строки пропускаются; пустой ID и повторный ID останавливают работу. Остальные пустые ячейки записываются как пустые поля. Исходная книга не сохраняется обратно. Режим x защищает существующий результат от перезаписи.
Прочитайте CSV обратно
После запуска откройте CSV через csv.reader с UTF-8 и newline="". Проверьте заголовок, число записей и контрольные значения. Количество физических строк файла не равно числу реплик: текст внутри поля может содержать переносы. Не считайте его простым разделением по запятой.
Правильный разбор описан в инструкции по колонкам CSV. Особенно проверьте запятые, кавычки, многострочные реплики и ID с ведущими нулями.
Учебный тест этого кода сохранил строковый ID 001, таймкод 00:10 и реплику с запятой, кавычками и переносом. Отдельный тест с формулой завершился до создания CSV. Эти проверки относятся к учебной книге, а не подтверждают корректность любой пользовательской таблицы.
Зафиксируйте ограничения переноса
CSV не переносит цвета, формулы, объединения ячеек, комментарии и связь между листами. Сохраните исходную книгу отдельно. Если важна редакторская заметка, выделите ей согласованное поле или отдельный файл вместо надежды на перенос оформления.
Пример предназначен для небольшой согласованной таблицы: книга и список строк занимают память. Для больших книг нужен отдельный процесс с ограничениями и проверкой размеров. Не включайте read_only наугад, считая это полной заменой контроля структуры.
Корректная выгрузка подтверждает сохранение выбранных значений, но не точность распознанной речи. Имена, числа и спорные реплики проверяйте по записи. В журнале укажите книгу, лист, версию скрипта и результат обратного чтения.
Учебный пример: отображение и фактическое значение
Условные строки демонстрируют причину строгой проверки типов.
| Ячейка | Фактическое значение | Решение |
|---|---|---|
| ID 001 | Текст «001» | Перенести как есть |
| ID 001 | Число 1 с форматом 000 | Остановиться и установить исходный ID |
| Таймкод | Формула | Подготовить проверенное значение |
Ни красивое отображение Excel, ни отсутствие ошибки скрипта не заменяют сверку спорного значения с источником.
Скрипт для согласованного листа Replicas
import csv
from openpyxl import load_workbook
fields = ["replica_id", "speaker", "timecode", "text"]
wb = load_workbook("interview.xlsx", data_only=False)
ws = wb["Replicas"]
if [c.value for c in ws[1]] != fields:
raise ValueError("Нужны четыре согласованных заголовка")
rows, seen = [], set()
for cells in ws.iter_rows(min_row=2):
if all(c.value is None for c in cells):
continue
if any(c.data_type == "f" for c in cells):
raise ValueError("Формула в строке " + str(cells[0].row))
values = ["" if c.value is None else c.value for c in cells]
if any(not isinstance(v, str) for v in values):
raise ValueError("Ячейка не текстовая: " + str(cells[0].row))
if not values[0] or values[0] in seen:
raise ValueError("Пустой или повторный replica_id")
seen.add(values[0])
rows.append(values)
wb.close()
with open("replicas.csv", "x", encoding="utf-8", newline="") as f:
writer = csv.writer(f)
writer.writerow(fields)
writer.writerows(rows)
print("Выгружено реплик:", len(rows))Частые вопросы
Можно выгрузить всю книгу одной командой?
У книги могут быть разные листы и структуры. Здесь выбран один согласованный лист.
Почему нельзя просто применить str()?
Число и отображение могут различаться. Исходные нули и формат времени не восстанавливаются автоматически.
Что происходит с формулами?
Пример останавливается. Вычисление формул не выполняется.
Перенос внутри реплики ломает CSV?
csv.writer корректно экранирует поле; читайте результат через csv.reader.