Предыстория: я фрилансер, основные деньги получаю, делая инструменты для редактирования xlsx файлов. Когда работы с Excel много, часто скапливаются задачи, что можно автоматизировать, но они делаются вручную. Я и пишу программы, что получают xlsx файл и обрабатывают данные с листов в удобный вид. Всё быстро, просто, понятно (одну кнопку нажать) и удобно.
пример
https://github.com/krakotay/steps-excel
Здесь не финальная версия, выложена с согласия заказчика
Но столкнулся с проблемой — редактирование уже имеющихся xlsx файлов это очень медленный процесс, гораздо медленнее чем чтение и запись. Поддержка такого режима есть только у openpyxl, там все операции очень долгие и требуют очень много ресурсов. "Точкой невозврата" стал случай, когда решение на openpyxl работало полчаса, съело всю доступную (из 32 гб) оперативку и 50 гб файла подкачки, и всё равно не справилось. Терпение кончилось быстрее. Потому я и навайбкодил написал своё решение. Новое решение (на компьютере клиента) справилось за 2 минуты с крошечным потреблением ОЗУ.
Вот сам проект. Ключевая часть написана на чистом Rust, имеются python-bindings. Лично я использую только с python 3.13, но и на 3.10-3.12 всё (по идее) работает.
Ключевые возможности
- 
Вставка таблицы, в конец или по указанным координатам. editor.append_table([["1", "2"], ["3", "4"]]) # в конец Worksheet editor.append_table_at([["=_xlfn.SUM(A1:B1)"], ['=_xlfn.SUM(A2:B2)']], "C1") editor.save("tests/test_sum_appended.xlsx")Поддерживаются формулы - их нужно писать в английской нотации, желательно начиная с =_xlfn.(считать их будет сам Excel)
- 
Сканирование файла from xlsx_append_py import PyXlsxScanner scanner = PyXlsxScanner(file_path) print(scanner.get_sheets()) assert scanner.get_sheets() == ["dog", "cat"] editor = scanner.open_editor("dog") assert editor.last_row_index("A") == 0 assert editor.last_row_index("B") == 0 assert editor.last_row_index("C") == 0 assert editor.last_row_index("D") == 0 assert editor.last_rows_index("A:D") == [0, 0, 0, 0] editor = scanner.open_editor("cat") assert editor.last_row_index("A") == 2 assert editor.last_row_index("B") == 9 assert editor.last_row_index("C") == 22 assert editor.last_row_index("D") == 15 assert editor.last_rows_index("A:D") == [2, 9, 22, 15]last_row_index это про индекс последней строчки, где имеются данные в нужном столбце. Т.е. если в столбце A есть данные в ячейке A1 и A1000, он покажет 1000 (ведь Excel считает с единицы). Если данных нет, то 0 (соответственно пустой столбец). Несколько разных листов тоже поддерживаются, в том числе на запись. Только каждый editor должен быть save(new_file_path)отдельно... а не всё вместе. Можно записывать в один файл
- 
Поддержка polars (не дефолтная, требует компиляции вручную) editor = PyXlsxEditor(os.path.join(base_dir, "../../test/test_polars.xlsx"), sheets[0]) editor.with_polars(df, None) editor.with_polars(df, "B15") editor.save(os.path.join(base_dir, "../../test/test_polars_appended.xlsx"))
все примеры из моих же тестов
UPD:
Провёл тестирование скорости
| Command | Mean [s] | Min [s] | Max [s] | Relative | 
|---|---|---|---|---|
| 
 | 7.444 ± 0.005 | 7.439 | 7.449 | 1.00 | 
| 
 | 179.239 ± 1.327 | 177.820 | 180.450 | 24.08 ± 0.18 | 
Ускорение в 24 раза. При падении потребления ОЗУ с ~3000+ мбайт до 37. 
Ссылка на замеры
причём openpyxl налажал




UPD 2:
Ускорил ещё сильнее
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative | 
|---|---|---|---|---|
| 
 | 471.7 ± 8.0 | 465.7 | 480.7 | 1.0 | 
Что удивительно, код на Rust написан полностью силами chatgpt o3, и он удивительно хорошо работает... Конечно без меня не обошлось, но я отвечал за биндинги к питону и дебаггинг. Тестировал, отлавливал ошибки. Надеюсь, проект вам понравился, а ещё лучше если пригодится!
Пока release выложены только на github. Как восстановлю доступ к PyPI, выложу и туда.
Комментарии (28)
 - Byaka8kaka21.07.2025 12:58- А чем Power Query не угодил?) Ну или на край VBA родной?)  - krakotay Автор21.07.2025 12:58- Power Query не подходит при нестандартных таблицах. Да и автоматизировать сложно. 
 VBA - я им плохо владею, он мне не нравится, он медленный, он плохо поддерживает кириллицу и постоянно блокируется Excel-ем. - Byaka8kaka21.07.2025 12:58- Power Query не подходит при нестандартных таблицах - Видимо я с такими еще не сталкивался) Счета обрабатываются вроде довольно легко, хоть там и при переводе в Power Query изначально жутко мясо показывает)  - krakotay Автор21.07.2025 12:58- Вы обрабатываете сами вручную, я правильно понимаю?  - Byaka8kaka21.07.2025 12:58- Нет конечно, формулу в Power Query один раз прописываю и дальше она уже сама все такие файлы обрабатывает) 
 Ну формулу руками пишу да, тут пока другого не придумал... - krakotay Автор21.07.2025 12:58- Понял. Я, скажу честно, плохо владею данным инструментом, потому пока сложно сказать. Можем ли мы связаться в телеграме? У меня ник тот же что и на хабре. Хочу со скриншотами обсудить 
 
 
 
 
 
 - whippoorwill21.07.2025 12:58- Честно скажу не читал статью. Но зацепил заголовок: "навайбкодил", "самый быстрый". Но в статье никаких замеров с аналогами нет. А с чего тогда вывод про самый быстрый? Потому что где то там используется Rust? Если только поэтому то вывод мне кажется поспешным а заголовок кликбейтным.  - krakotay Автор21.07.2025 12:58- "[решение на openpyxl] съело всю доступную (из 32 гб) оперативку и 50 гб файла подкачки, и всё равно не справилось. Терпение кончилось быстрее. Потому я и - навайбкодилнаписал своё решение. Новое решение (на компьютере клиента) справилось за 2 минуты с крошечным потреблением ОЗУ "- Но да, надо отдельно провести тесты. Я в основном судил "на глаз", там разница очень заметная. - rust выбрал потому что я его знаю. Чистый python довольно медленный. 
  - krakotay Автор21.07.2025 12:58- Сделал тесты, x24 по скорости. А также (личные замеры) потребление памяти сократилось с 3000 мб до 37 мб. Причём openpyxl ещё таблицу сломал, Excel потребовал восстановления. - UPD: Обновил и саму статью. А вы мне ещё минусов наставили... 
 
 - pol_pot21.07.2025 12:58- Почему редактирование очень медленное и как оно могло сожрать 80гб памяти. - Там же всего и надо распаковать зип архив с xml файлами, внести в них правки и запаковать обратно. Питон не должен был стать узким местом.  - krakotay Автор21.07.2025 12:58 - Скоро выложу тесты. Таблица там элементарная, потребление ОЗУ через мою библиотеку 37 мб было - UPD: Выложил 
 
 - withkittens21.07.2025 12:58- // Find the row containing the target cell. let row_marker = format!("<row r=\"{}\"", row_num); if let Some(row_start) = self .sheet_xml .windows(row_marker.len()) .position(|w| w == row_marker.as_bytes())- Это ваша библиотека так с XML работает?  - Mingun21.07.2025 12:58- Навайбкожено видимо. Потом в куче мест раскопирован шаблон работы, подозрительно напоминающий оной из readme, явно видно, что бездумной нейросетью: - весь файл вычитали в массив, но для чтения использует копирующие методы. - Reader<[u8]>, который создается, может возвращать события, заимствующие данные событий из общего массива. Тем более, что все прочитанные таким образом события сразу выкидываются
- подразумевается UTF-8. Хотя вряд ли будет что-то другое. По хорошему надо пользоваться декодером, который дает - Reader
- в одном месте - Readerсоздали и настроили, а потом ниже еще раз (а первый не использовался)
  - krakotay Автор21.07.2025 12:58- Спасибо большое! Пока по UTF-8 сделал костыль, блокировка не UTF-8 сразу после ридера. Остальное исправил 
 
 
 - edyatl21.07.2025 12:58- редактирование уже имеющихся xlsx файлов это очень медленный процесс, гораздо медленнее чем чтение и запись. Поддержка такого режима есть только у openpyxl, там все операции очень долгие и требуют очень много ресурсов. "Точкой невозврата" стал случай, когда решение на openpyxl работало полчаса, съело всю доступную (из 32 гб) оперативку и 50 гб файла подкачки, и всё равно не справилось. - Простите, что!? Можете точный пример привести, что за операцию вы делали, которая привела к таким последствиям? Подозреваю, что проблема не в Python. Он обрабатывает несколько гигабайтные файлы с миллионами строк в таблицах легко и не напрягаясь.  - krakotay Автор21.07.2025 12:58- Будь моя воля, показал бы оригинальный файл, но он конфиденциальный. В ближайшее время попробую создать имитацию с фальшивыми данными. 
 
 - grixis21.07.2025 12:58- Хорош! И пусть не верят и относятся к вайбкоду плохо, но чатгпт для меня написал уже с десяток разных ботов для телеги и даже пару игр с мультиплеером на html+js  - dabchinsky21.07.2025 12:58- Примеры игр можно? Флепи берд и тетрис можно найти в Гугле по первому запросу, чат жпт тут не нужен. 
 
 
           
 





igumnov
Круто, бро!
krakotay Автор
Спасибо!