Hallo,
hat jemand von euch Erfahrung mit dem pyExcelerator?
Das ist ein ziemlich gutes Tool für Excel2CSV und erstellen von Excel-Sheets mit Hilfe von Python.
Leider fehlt eine Dokumentation und ich Suche eine Möglichkeit, bzw die Variablen oder Funktionen um auch Formatierungen wie Farben und ähnliches auszuwerten.
Es gibt eine voregefertigte Klasse um die Zellenwerte auch Formeln und so auszulesen, aber sie gibt mir immer nur den Inhalt zurück.
Für sachdienliche Hinweise wäre ich mehr als Dankbar.
Gruss
Jay-Pi
pyExcelerator - Excel-Dokument auslesen (Formatierung)
Hoi und willkommen im Forum,
bist Du so nett und läßt uns ein wenig von Deinem relevanten Code sehen? Dann können wir nämlich u. U. leichter darauf kommen, wo der Fehler liegt .
Gruß,
Christian
bist Du so nett und läßt uns ein wenig von Deinem relevanten Code sehen? Dann können wir nämlich u. U. leichter darauf kommen, wo der Fehler liegt .
Gruß,
Christian
Folgendes liest die Zellenwerte in eine Matrix und gibt diese dann aus.
Die verwendete Funktion Hauptteil sieht etwa so aus:
Das was mir fehlt ist eine Auswertung des XF-Records und FONT.
Eine gute Doku zum BIFF8 Format habe ich unter:
http://www.xlam.ch/soscq/dateiformat.htm
und bei oO.org
http://sc.openoffice.org/excelfileformat.pdf
gefunden.
Den Quellcode vom pyExcelerator findet man hier:
http://www.sourceforge.net/projects/pyexcelerator[/code]
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: windows-1251 -*-
# Copyright (C) 2005 Kiseliov Roman
__rev_id__ = """$Id: xls2csv.py,v 1.1 2005/10/26 07:44:24 rvk Exp $"""
from pyExcelerator import *
import sys
me, args = sys.argv[0], sys.argv[1:]
if args:
for arg in args:
print >>sys.stderr, 'extracting data from', arg
for sheet_name, values in parse_xls(arg, 'cp1251'): # parse_xls(arg) -- default encoding
matrix = [[]]
print 'Sheet = "%s"' % sheet_name.encode('cp866', 'backslashreplace')
print '----------------'
for row_idx, col_idx in sorted(values.keys()):
v = values[(row_idx, col_idx)]
if isinstance(v, unicode):
v = v.encode('cp866', 'backslashreplace')
else:
v = `v`
v = '"%s"' % v.strip()
last_row, last_col = len(matrix), len(matrix[-1])
while last_row <= row_idx:
matrix.extend([[]])
last_row = len(matrix)
while last_col < col_idx:
matrix[-1].extend([''])
last_col = len(matrix[-1])
matrix[-1].extend([v])
for row in matrix:
csv_row = ', '.join(row)
print csv_row
else:
print 'usage: %s (inputfile)+' % me
Die verwendete Funktion Hauptteil sieht etwa so aus:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: windows-1251 -*-
# Copyright (C) 2005 Roman V. Kiseliov
# All rights reserved.
# ...
import struct
encodings = {
0x016F: 'ascii', #ASCII
0x01B5: 'cp437', #IBM PC CP-437 (US)
0x02D0: 'cp720', #IBM PC CP-720 (OEM Arabic)
0x02E1: 'cp737', #IBM PC CP-737 (Greek)
#...
}
biff8 = True
SST = {}
sheets = []
sheet_names = []
values = {}
ws_num = 0
BOFs = 0
EOFs = 0
# Inside MS Office document looks like filesystem
# We need extract stream named 'Workbook' or 'Book'
ole_streams = CompoundDoc.Reader(filename).STREAMS
if 'Workbook' in ole_streams:
workbook_stream = ole_streams['Workbook']
elif 'Book' in ole_streams:
workbook_stream = ole_streams['Book']
else:
raise Exception, 'No workbook stream in file.'
workbook_stream_len = len(workbook_stream)
stream_pos = 0
# Excel's method of data storing is based on
# ancient technology "TLV" (Type, Length, Value).
# In addition, if record size grows to some limit
# Excel writes CONTINUE records
while stream_pos < workbook_stream_len and EOFs <= ws_num:
rec_id, data_size = unpack('<2H', workbook_stream[stream_pos:stream_pos+4])
stream_pos += 4
rec_data = workbook_stream[stream_pos:stream_pos+data_size]
stream_pos += data_size
if rec_id == 0x0809: # BOF
#print 'BOF',
BOFs += 1
ver, substream_type = unpack('<2H', rec_data[:4])
if substream_type == 0x0005:
# workbook global substream
biff8 = ver >= 0x0600
elif substream_type == 0x0010:
# worksheet substream
pass
else: # skip chart stream or unknown stream
# stream offsets may be used from BOUNDSHEET record
rec_id, data_size = unpack('<2H', workbook_stream[stream_pos:stream_pos+4])
while rec_id != 0x000A: # EOF
#print 'SST CONTINUE'
stream_pos += 4
stream_pos += data_size
rec_id, data_size = unpack('<2H', workbook_stream[stream_pos:stream_pos+4])
#print 'BIFF8 == ', biff8
elif rec_id == 0x000A: # EOF
#print 'EOF'
if BOFs > 1:
sheets.extend([values])
values = {}
EOFs += 1
elif rec_id == 0x0042: # CODEPAGE
cp , = unpack('<H', rec_data)
#print 'CODEPAGE', hex(cp)
if not encoding:
encoding = encodings[cp]
#print encoding
elif rec_id == 0x0085: # BOUNDSHEET
#print 'BOUNDSHEET',
ws_num += 1
b = process_BOUNDSHEET(biff8, rec_data)
sheet_names.extend([b])
#print b.encode('cp866')
elif rec_id == 0x00FC: # SST
#print 'SST'
sst_data = rec_data
sst_continues = []
rec_id, data_size = unpack('<2H', workbook_stream[stream_pos:stream_pos+4])
while rec_id == 0x003C: # CONTINUE
#print 'SST CONTINUE'
stream_pos += 4
rec_data = workbook_stream[stream_pos:stream_pos+data_size]
sst_continues.extend([rec_data])
stream_pos += data_size
rec_id, data_size = unpack('<2H', workbook_stream[stream_pos:stream_pos+4])
SST = process_SST(sst_data, sst_continues)
elif rec_id == 0x00FD: # LABELSST
#print 'LABELSST',
r, c, i = process_LABELSST(rec_data)
values[(r, c)] = SST[i]
#print r, c, SST[i].encode('cp866')
elif rec_id == 0x0204: # LABEL
#print 'LABEL',
r, c, b = process_LABEL(biff8, rec_data)
values[(r, c)] = b
#print r, c, b.encode('cp866')
elif rec_id == 0x00D6: # RSTRING
#print 'RSTRING',
r, c, b = process_RSTRING(biff8, rec_data)
values[(r, c)] = b
#print r, c, b.encode('cp866')
elif rec_id == 0x027E: # RK
#print 'RK',
r, c, b = process_RK(rec_data)
values[(r, c)] = b
#print r, c, b
elif rec_id == 0x00BD: # MULRK
#print 'MULRK',
for r, c, b in process_MULRK(rec_data):
values[(r, c)] = b
#print r, c, b
elif rec_id == 0x0203: # NUMBER
#print 'NUMBER',
r, c, b = process_NUMBER(rec_data)
values[(r, c)] = b
#print r, c, b
elif rec_id == 0x0006: # FORMULA
#print 'FORMULA',
r, c, x = unpack('<3H', rec_data[0:6])
if rec_data[12] == '\xFF' and rec_data[13] == '\xFF':
if rec_data[6] == '\x00':
got_str = False
if ord(rec_data[14]) & 8:
# part of shared formula
rec_id, data_size = unpack('<2H', workbook_stream[stream_pos:stream_pos+4])
stream_pos += 4
rec_data = workbook_stream[stream_pos:stream_pos+data_size]
stream_pos += data_size
if rec_id == 0x0207: # STRING
got_str = True
elif rec_id not in (0x0221, 0x04BC, 0x0236, 0x0037, 0x0036):
raise Exception("Expected ARRAY, SHRFMLA, TABLEOP* or STRING record")
if not got_str:
rec_id, data_size = unpack('<2H', workbook_stream[stream_pos:stream_pos+4])
stream_pos += 4
rec_data = workbook_stream[stream_pos:stream_pos+data_size]
stream_pos += data_size
if rec_id != 0x0207: # STRING
raise Exception("Expected STRING record")
values[(r, c)] = unpack2str(biff8, rec_data)
elif rec_data[6] == '\x01':
# boolean
v = ord(rec_data[8])
values[(r, c)] = bool(v)
elif rec_data[6] == '\x02':
# error
v = ord(rec_data[8])
if v in ExcelMagic.error_msg_by_code:
values[(r, c)] = ExcelMagic.error_msg_by_code[v]
else:
values[(r, c)] = u'#UNKNOWN ERROR!'
elif rec_data[6] == '\x03':
# empty
values[(r, c)] = u''
else:
raise Exception("Unknown value for formula result")
else:
# 64-bit float
d, = unpack("<d", rec_data[6:14])
values[(r, c)] = d
encoding = None
return zip(sheet_names, sheets)
Das was mir fehlt ist eine Auswertung des XF-Records und FONT.
Eine gute Doku zum BIFF8 Format habe ich unter:
http://www.xlam.ch/soscq/dateiformat.htm
und bei oO.org
http://sc.openoffice.org/excelfileformat.pdf
gefunden.
Den Quellcode vom pyExcelerator findet man hier:
http://www.sourceforge.net/projects/pyexcelerator[/code]
Hallo,
tut mir leid: Ich habe Dich vorhin in einem Anfall geistiger Umnachtung mißverstanden . So weit ich weiß, ist es nicht möglich Formatierungen mittels pyexcelerator wiederzubekommen. Ich verwende das Modul auch, da ich hauptsächlich unter Linux arbeite aber manchmal Daten nach Excel exportieren muß - aber so weit ich sehe, bin ich der Einzige hier im Forum.
Was Du mit erhälst ist eine Liste:
x[0] - der Inhalt eines Worksheets
x[0][0] - Name des Worksheets
x[0][1] - die Daten in Form eines dicts mit den Zellen als tuple von Spalte/Zeile, den den Schlüssel darstellen. Zurück bekommst Du nur den Wert (i.d.R einen Unicode-String, eine Zahl, aber noch nicht einmal Formeln ).
(Das alles weißt Du wahrscheinlich längst, aber ich schreibe mal der Vollständigkeit halber, schließlich gibt es ähnliche Fragen ab und an mal.)
Die Situation ist etwas unbefriedigend, aber es gibt win32com - einfach mal hier im Forum danach suchen.
Gruß,
Christian
tut mir leid: Ich habe Dich vorhin in einem Anfall geistiger Umnachtung mißverstanden . So weit ich weiß, ist es nicht möglich Formatierungen mittels pyexcelerator wiederzubekommen. Ich verwende das Modul auch, da ich hauptsächlich unter Linux arbeite aber manchmal Daten nach Excel exportieren muß - aber so weit ich sehe, bin ich der Einzige hier im Forum.
Was Du mit
Code: Alles auswählen
x = parse_xls('ein.xls')
x[0] - der Inhalt eines Worksheets
x[0][0] - Name des Worksheets
x[0][1] - die Daten in Form eines dicts mit den Zellen als tuple von Spalte/Zeile, den den Schlüssel darstellen. Zurück bekommst Du nur den Wert (i.d.R einen Unicode-String, eine Zahl, aber noch nicht einmal Formeln ).
(Das alles weißt Du wahrscheinlich längst, aber ich schreibe mal der Vollständigkeit halber, schließlich gibt es ähnliche Fragen ab und an mal.)
Die Situation ist etwas unbefriedigend, aber es gibt win32com - einfach mal hier im Forum danach suchen.
Gruß,
Christian
PS Ich habe vor gut einem halben Jahr einmal den Entwickler Roman Kiseliov angeschrieben. Zu diesem Zeitpunkt also konnte man ihn noch kontaktieren unter angegebenen Adresse. Und beantwortet auch alle Frage rel. zügig. Allerdings scheint er nicht an einer Weiterentwicklung des Moduls interessiert zu sein.
Gruß,
Christian
Gruß,
Christian
Hi,
danke trotzdem fürs nachschauen.
Ich habe es in die Richtung bereits hinbekommen, allerdings nicht ausgereift.
Habe in der parse_xls() noch eine Suche nach XF-Record und FONT-Record eingebaut.
Wenn ich da wieter bin melde ich mich hierzu nochmal.
Aber mal was anderes.
Hatte jetzt ein Problem mit Umlauten Äs und Üs und so, da bricht der Parser ab, weill das encode('cp688') oder wie es nochmal hieß nicht klappt.
Schonmal was in der Richtung angepasst?
Gruss
JP
danke trotzdem fürs nachschauen.
Ich habe es in die Richtung bereits hinbekommen, allerdings nicht ausgereift.
Habe in der parse_xls() noch eine Suche nach XF-Record und FONT-Record eingebaut.
Wenn ich da wieter bin melde ich mich hierzu nochmal.
Aber mal was anderes.
Hatte jetzt ein Problem mit Umlauten Äs und Üs und so, da bricht der Parser ab, weill das encode('cp688') oder wie es nochmal hieß nicht klappt.
Schonmal was in der Richtung angepasst?
Gruss
JP
pyExcelerator kann nur ein relativ altes Excel-Format lesen. Ich glaube bei `Excel 95` hört es auf. Dafür kann man damit auch Excel-Dateien schreiben.
Das stimmt so nicht ganz.BlackJack hat geschrieben:pyExcelerator kann nur ein relativ altes Excel-Format lesen.
Ich verwende den pyExcelerator-6.0.3a.
Der Importiert auf jeden Fall Excel 2000 (getestet),
laut Quellcode wird meines erachtens immer mit BIFF8 gearbeitet, also 97 und 2000, aber auch Funktionen für Werte in älteren Versionen habe ich gesehen.
Die offizielle Beschreibung sagt:
GrussGenerating Excel 97+ files with Python 2.4+ (need decorators), importing Excel 95+ files, support for UNICODE in Excel files, using variety of formatting features and printing options, Excel files and OLE2 compound files dumper. No need in Windows/COM
JP
Hallo,
nachdem ich jetzt fastalles selbst gebaut habe, was mit Formatierungen zu tun hat (XF, FONT, FORMAT), bin ich wegen Datumsdarstellungen nochmal auf xlrd gestossen.
Aber ich komm nicht so ganz zu rande mit den Klassen/Modulen.
Weiss jemand, wie ich auf die Formatierungen zugreifen kann?
Ich suche etwas um von dem XF Record Index auf das XF Record (Class) zugreifen kann, um die Werte wiederum auszulesen.
Ein paar Beispiele:
Ich finde entweder die Funktionen nicht, oder weiss nicht, wie ich die Listen oder Maps benutze, die mit den Formatierungen erstellt werden.
Ich möchte zum Beispiel die Schriftgröße auslesen.
Das steht in zb in der Klasse Rowinfo.
Bekomme aber nur den initial Wert:
Gruss
JP
PS: Zur Frage weiter odebn:
pyExcelerator ist ein umfangreiches Modul zum erstellen von Excel-Dateien
xlrd dagegen ist spezialisiert aus lesen und speichert alle Zellen und Dokumentinformationen, um sie direkt abzurufen.
nachdem ich jetzt fastalles selbst gebaut habe, was mit Formatierungen zu tun hat (XF, FONT, FORMAT), bin ich wegen Datumsdarstellungen nochmal auf xlrd gestossen.
Aber ich komm nicht so ganz zu rande mit den Klassen/Modulen.
Weiss jemand, wie ich auf die Formatierungen zugreifen kann?
Ich suche etwas um von dem XF Record Index auf das XF Record (Class) zugreifen kann, um die Werte wiederum auszulesen.
Ein paar Beispiele:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8
import xlrd
book = xlrd.open_workbook("test.xls", formatting_info=True)
print "The number of worksheets is", book.nsheets
print "Worksheet name(s):", book.sheet_names()
sh = book.sheet_by_index(2)
print sh.name, sh.nrows, sh.ncols
print "Cell A11 is", sh.cell_value(rowx=10, colx=0)
print "Cell mit Typ:Wert, (XF:Index)", sh.cell(rowx=10, colx=0)
xf = sh.cell_xf_index(rowx=10, colx=0)
print "XF", xf
dt = xlrd.xldate_as_tuple(sh.cell_value(rowx=10, colx=0),book.datemode)
print dt
import datetime
print datetime.datetime(*dt)
Ich möchte zum Beispiel die Schriftgröße auslesen.
Das steht in zb in der Klasse Rowinfo.
Bekomme aber nur den initial Wert:
Code: Alles auswählen
print xlrd.sheet.Rowinfo.height
JP
PS: Zur Frage weiter odebn:
pyExcelerator ist ein umfangreiches Modul zum erstellen von Excel-Dateien
xlrd dagegen ist spezialisiert aus lesen und speichert alle Zellen und Dokumentinformationen, um sie direkt abzurufen.
Hallo,
ich bin schon ein bischen weitergekommen.
Ein Zugriff auf ein bestimmtes XF Element könnte so aussehen:
Allerdings weiss ich jetzt nicht, wie ich zB auf die Elemente des UnterObjects komme. ( background (XFBackground object): )
ich bin schon ein bischen weitergekommen.
Ein Zugriff auf ein bestimmtes XF Element könnte so aussehen:
Code: Alles auswählen
#37 ist ein Beispiel index entweder den Wert in der Zelle (sihe oben), oder Wert -1
book.xf_list[37].dump()
Code: Alles auswählen
_alignment_flag: 0
_background_flag: 0
_border_flag: 0
_font_flag: 0
_format_flag: 1
_protection_flag: 0
alignment (XFAlignment object):
hor_align: 0
indent_level: 0
rotation: 0
shrink_to_fit: 0
text_direction: 0
text_wrapped: 0
vert_align: 2
background (XFBackground object):
background_colour_index: 65
fill_pattern: 0
pattern_colour_index: 64
border (XFBorder object):
bottom_colour_index: 0
bottom_line_style: 0
diag_colour_index: 0
diag_down: 0
diag_line_style: 0
diag_up: 0
left_colour_index: 0
left_line_style: 0
right_colour_index: 0
right_line_style: 0
top_colour_index: 0
top_line_style: 0
font_index: 0
format_key: 20
is_style: 0
lotus_123_prefix: 0
parent_style_index: 0
protection (XFProtection object):
cell_locked: 1
formula_hidden: 0
xf_index: 37
OK ich habe den Fehler gefunden.
Ich habe den falschen "key" benutzt. Nicht den Klassen namen benötige ich, sondern das Attribut, welches als instance die Klasse hat.
also background anstatt XFBackground
Ich habe den falschen "key" benutzt. Nicht den Klassen namen benötige ich, sondern das Attribut, welches als instance die Klasse hat.
also background anstatt XFBackground
Code: Alles auswählen
book.xf_list[37].background.background_colour_index