3 метода парсинга Excel 2003 XML формата в Python 3

Разбирать формат Excel 2003-2015 умеют многие библиотеки для Python 3. Здесь описан парсинг XML-формата Excel 2003, который приходится разбирать с помощью XML-библиотек. И бонусом метод, работающий только на Windows с установленным Excel.

XML.SAX: требовательный к структуре

Метод требователен к структуре файла и, если будет пропущен тэг или другая ошибка, то на этом все и остановится. Как преимущество, библиотека сразу доступна в Python.

import xml.sax

class ExcelHandler(xml.sax.ContentHandler):
    def __init__(self):
        self.chars = [ ]
        self.cells = [ ]
        self.rows = [ ]
        self.tables = [ ]
        
    def characters(self, content):
        self.chars.append(content)
        
    def startElement(self, name, atts):
        if name=="Cell":
            self.chars = [ ]
        elif name=="Row":
            self.cells=[ ]
        elif name=="Table":
            self.rows = [ ]
        
    def endElement(self, name):
        if name=="Cell":
            self.cells.append(''.join(self.chars))
        elif name=="Row":
            self.rows.append(self.cells)
        elif name=="Table":
            self.tables.append(self.rows)

excelHandler = ExcelHandler()
xml.sax.parse('excel2003.xml', excelHandler)

# Parsed sheets
excelHandler.tables

Beautiful Soup: позволяет расслабиться

Внешняя библиотека, поддерживаемая сообществом. Позволяет разбирать структурированные файлы, включая HTML-страницы с пропусками тэгов. Python 3+ поддерживается только 4 версией.

Установка на Windows (Anaconda):
pip install bs4

Установка на Ubuntu:
apt-get install libxml2-dev libxslt1-dev python-dev
pip install lxml
pip install bs4

Код примитивнее предыдущего примера:

from bs4 import BeautifulSoup

handler = open('excel2003.xml').read()
soup = BeautifulSoup(handler, 'lxml')

tables = []
for table in soup.findAll('ss:table'):
    rows = []
    for row in table.findAll('ss:row'):
        cells = []
        for cell in row.findAll('ss:cell'):
            cells.append(cell.find('ss:data').get_text())
        rows.append(cells)
    tables.append(rows)

# Parsed sheets
tables

Only Windows: конвертация XLS в CSV

Если мы не можем работать с файлом напрямую, тогда будем работать с CSV. Но для этого нам нужен Windows, Excel и VBScript.

Создаем excel2csv.vbs со следующим кодом:

if WScript.Arguments.Count < 3 Then
WScript.Echo "Please specify the source and the destination files. Usage: ExcelToCsv <xls/xlsx source file> "
Wscript.Quit
End If

csv_format = 6

Set objFSO = CreateObject("Scripting.FileSystemObject")

src_file = objFSO.GetAbsolutePathName(Wscript.Arguments.Item(0))
dest_file = objFSO.GetAbsolutePathName(WScript.Arguments.Item(1))
worksheet_number = CInt(WScript.Arguments.Item(2))

Dim oExcel
Set oExcel = CreateObject("Excel.Application")

Dim oBook
Set oBook = oExcel.Workbooks.Open(src_file)
oBook.Worksheets(worksheet_number).Activate

oBook.SaveAs dest_file, csv_format

oBook.Close False
oExcel.Quit

Затем вызываем созданный скрипт из Python-а и используем полученный CSV-файл:

from subprocess import call
filename = 'excel2003.xml' # Или любой другой формат
csv_filename = filename + '.csv'
call(['cscript.exe', 'excel2csv.vbs', filename, csv_filename, '1'])

csv_filename # Открываем любым CSV-парсером.