Python. Работаем с xls через xlwt/xlrd и python-uno
Понадобилось без потери данных и функциональности модифицировать xls документы, то есть мы имеем несколько листов в документе, на одном из листов есть фильтры, списки и прочие компоненты современного екселя.
Первое что приходит на ум - это старый-добрый Python Excel (xlwt/xlrd), попробуем реализовать модификацию ячейки с помощью этого инструмента, а потом перейдем к PyUNO.
Python Excel: xlwt, xlrd, xlutils
Более подробно об этих пакетах можно почитать на странице Python Excel.
Для начала установим их:
sudo pip install xlwt xlrd xlutils
А теперь пример кода:
import xlwt, xlrd from xlutils.copy import copy as xlcopy source_filename = "/tmp/example.xls" destination_filename = "/tmp/example_new.xls" read_book = xlrd.open_workbook(source_filename, on_demand=True) # Открываем исходный документ read_sheet = read_book.get_sheet(0) # Читаем из первого листа write_book = xlcopy(read_book) # Копируем таблицу в память, в неё мы ниже будем записывать write_sheet = write_book.get_sheet(0) # Будем записывать в первый лист write_sheet.write(0, 0, read_sheet.cell_value(0, 0) + 42) # Прибавим к значению из ячейки "A1" число 42 write_book.save(destination_filename) # Сохраняем таблицу
Простейший пример использования испортит нам документ, в котором есть формулы, фильтры и прочие компоненты таблицы, поэтому это решение нам не подходит.
PyUNO
Теперь попробуем python-uno, его мы тоже установим, в добавок нам необходимо установить libreoffice, так как именно в libreoffice мы и будем производить изменения:
sudo apt-get install python-uno libreoffice
Пакеты python-uno и libreoffice можно установить на разные хосты, так как первый будет клиентом для второго.
Теперь запустим libreoffice на локальном хосте:
libreoffice --accept="socket,host=localhost,port=2002;urp;StarOffice.ServiceManager"
Пример кода по модификации одной ячейки через PyUNO:
import uno source_filename = "/tmp/example.xls" destination_filename = "/tmp/example_new.xls" def get_document(filename): """Небольшая обертка для корретного открытия документа""" local = uno.getComponentContext() resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local) context = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext") desktop = context.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", context) document = desktop.loadComponentFromURL(uno.systemPathToFileUrl(filename), "_blank", 0, tuple()) return document document = get_document(source_filename) # Окроем исходный документ sheet = document.getSheets().getByIndex(0) # Получем первый лист cell = sheet.getCellByPosition(0, 0) # Получим необходимую нам ячейку cell.setString(int(cell.getString()) + 42) # И запишем в неё новый результат # Сохраняем документ document.storeToURL(uno.systemPathToFileUrl(destination_filename), ())
Код далек от идеала, но для презентации возможностей это самое то.
Результат был достигнут - все компоненты в таблице остались не тронутыми, поменялась лишь ячейка, которую мы меняли.
Вообщем python-uno идеально подходит для автоматизации работы с офисными документами без потерь!
Комментарии
Ну еще стоило отметить, что libreoffice - форк OO, так что можно спокойно работать и с ним.
FYI https://github.com/whitehat2k9/PyExcelerate
Спасибо, очень полезный пост!
может стоило попробовать formatting_info=True?
xlrd.open_workbook(file,formatting_info=True)
Оставьте свой комментарий