28 февраля 2012 г. Excel xls Python

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 идеально подходит для автоматизации работы с офисными документами без потерь!

Рекомендую почитать

Комментарии

Святослав 1 марта 2012 г. 14:21

Ну еще стоило отметить, что libreoffice - форк OO, так что можно спокойно работать и с ним.

FYI https://github.com/whitehat2k9/PyExcelerate

Спасибо, очень полезный пост!

хз что за поле 29 января 2014 г. 11:21

может стоило попробовать formatting_info=True?
xlrd.open_workbook(file,formatting_info=True)

Оставьте свой комментарий

Markdown