2013-07-24 19 views
8

Chciałem zaimportować plik zawierający tekst, liczby i daty za pomocą xlrd na Pythonie.Python: xlrd wymagające daty z float

Próbowałem coś takiego:

if "/" in worksheet.cell_value: 
    do_this 
else: 
    do_that 

Ale to było bezużyteczne jak to ostatnie odkryte daty są przechowywane jako pływaki, a nie ciągi. Aby przekonwertować je do typu datetime, zrobiłem:

try: 
    get_row = str(datetime.datetime(*xlrd.xldate_as_tuple(worksheet.cell_value(i, col - 1), workbook.datemode))) 
except: 
    get_row = unicode(worksheet.cell_value(i, col - 1)) 

Mam wyjątek w miejscu, gdy komórka zawiera tekst. Teraz chcę, aby liczby były liczbami, a daty datami, ponieważ teraz wszystkie liczby są konwertowane na daty.

Wszelkie pomysły?

+0

Nie powinieneś oczekiwać, że Excel rozróżnia daty i liczby, jeśli nie możesz. – pnuts

Odpowiedz

8

Cóż, nieważne, znalazłem rozwiązanie i oto jest!

try: 
    cell = worksheet.cell(row - 1, i) 
    if cell.ctype == xlrd.XL_CELL_DATE: 
     date = datetime.datetime(1899, 12, 30) 
     get_ = datetime.timedelta(int(worksheet.cell_value(row - 1, i))) 
     get_col2 = str(date + get_)[:10] 
     d = datetime.datetime.strptime(get_col2, '%Y-%m-%d') 
     get_col = d.strftime('%d-%m-%Y') 
    else: 
     get_col = unicode(int(worksheet.cell_value(row - 1, i))) 
except: 
    get_col = unicode(worksheet.cell_value(row - 1, i)) 

Trochę wyjaśnienia: okazuje się, że z xlrd rzeczywiście można sprawdzić typ komórki i sprawdzić, czy jest to data, czy nie. Ponadto, wydaje się, że program Excel ma dziwny sposób na zaoszczędzenie dziennych godzin. Zapisuje je jako pływające (lewa część przez kilka dni, prawa część przez wiele godzin), a następnie zajmuje określoną datę (1899, 12, 30, wydaje się działać poprawnie) i dodaje dni i godziny z pływaka, aby utworzyć datę. Tak więc, aby utworzyć datę, którą chciałem, dodałem je i zachowałem tylko 10 pierwszych liter ([: 10]), aby pozbyć się godzin (00.00.00 lub coś takiego ...). Zmieniłem także kolejność dni_miesięcy-lat, ponieważ w Grecji używamy innego zamówienia. Na koniec ten kod sprawdza również, czy można przekonwertować liczbę na liczbę całkowitą (nie chcę, aby pokazywano w moim programie ...) i jeśli wszystko zawiedzie, po prostu używa komórki takiej, jaka jest (w ciągi w komórkach ...). Mam nadzieję, że okaże się, że przydatne, myślę, że są inne wątki, które mówią, że jest to niemożliwe lub coś ...

+1

Program Excel w systemie Windows/Mac różni się w punkcie początkowym - do tego służy atrybut datemode w skoroszycie - dlatego należy go używać, a nie kodować mocno datetime. Możliwe jest również (choć mało prawdopodobne), że poprzez skracanie elementów z float (ponieważ tak jest zapisywana data/czas w Excelu), można zgolić wystarczająco dużo informacji, które wyłączyłyby datę o jeden dzień. Co było bliżej do poprawienia na tym jest twoje pierwotne pytanie, ale po prostu dodaj w komórce sprawdzić typ i gotowe ... –

+0

Godziny zawarte w float są wszystkie 00.00.00, więc to nic ... I to, czego użyłem w pierwotnym pytaniu, było trudne w obsłudze, może nawet w błędzie, nie wiem dlaczego, więc nie mogłem zmienić kolejności daty (i to jest istotne ...) – Antoni4040

+0

Formuła nie jest poprawna na Windows też np., Jeśli 'cell_value = 30' twoja formuła zwraca' 29-01-1900', to powinno zwrócić '30-01-1900', zobacz [Jak skonwertować dany numer porządkowy (z Excela) na datę] (http://stackoverflow.com/q/29387137/4279). LUB (lepiej) użyj metod 'xlrd' jak pokazano w [@ gryynougat 'odpowiedzi/komentarzy] (http://stackoverflow.com/a/18016189/4279). Również 'date + get_' jest już obiektem datetime: nie trzeba go konwertować na str, tylko aby przekonwertować go z powrotem do datetime, tylko aby przekonwertować go na str w innym formacie - po prostu przekonwertuj go do pożądanego formatu bezpośrednio za pomocą'. strftime() '. – jfs

9

Myślę, że można zrobić to dużo prostsze poprzez większe wykorzystanie dostępnych narzędzi w xlrd:

cell_type = worksheet.cell_type(row - 1, i) 
cell_value = worksheet.cell_value(row - 1, i) 

if cell_type == xlrd.XL_CELL_DATE: 
    # Returns a tuple. 
    dt_tuple = xlrd.xldate_as_tuple(cell_value, workbook.datemode) 
    # Create datetime object from this tuple. 
    get_col = datetime.datetime(
     dt_tuple[0], dt_tuple[1], dt_tuple[2], 
     dt_tuple[3], dt_tuple[4], dt_tuple[5] 
    ) 
elif cell_type == xlrd.XL_CELL_NUMBER: 
    get_col = int(cell_value) 
else: 
    get_col = unicode(cell_value) 
+6

Dwie rzeczy. (1) Możesz rozpakować krotkę używając operatora '*', więc 'get_col = datetime.datetime (* dt_tuple)'. (2) Od Xlrd 0.9.3 istnieje funkcja "xldate.xldate_as_datetime", która może być użyta zamiast 'xldate_as_tuple'. (Aby być uczciwym, 0.9.3 jest nowszy niż ta odpowiedź.) –