2012-04-05 6 views
0

Ich habe ein Skript geschrieben, das Werte für ein bestimmtes Datum in einem Excel-Blatt ändert. Wenn ich eine neue Excel-Datei unter Verwendung von copy erstelle, wird alles bis auf den Jahresteil des Datums korrekt kopiert. Zum Beispiel wird es vom 04.05.2012 bis zum 04.05.2008 gehen. Es scheint, dass alle Daten vier Jahre zurückreichen. Hier ist der Code:Python xlutils Kopien über falsches Jahr

def exceledit(): 
#open excel sheet               
import xlrd, xlwt, xlutils 
import datetime 
from xlutils.copy import copy 
print 'Opening excel sheet...' 
book = xlrd.open_workbook('test.xls', on_demand=True, formatting_info=True) 
print 'Creating and editing new excel sheet...' 
wbook = copy(book) 
print 'Done creating new excel sheet' 

sh = book.sheet_by_index(0) 
#iterate through dates in excel sheet          
for colnum in range(sh.ncols): 
    date = sh.cell_value(3, colnum+4) 
    #if xlrd finds a date             
    if date: 
     #grab date data              
     year, month, day, hour, minute, second = xlrd.xldate_as_tuple(date\ 
    , book.datemode) 
     #if dates are within the month currently being edited    
     if month == 04: 
      #format excel date information to work with parkh dict   
      format = str(month) + "/" + str(day) + "/" + str(year)   
      print 'Editing ' + format 
      #clear cells to eliminate old information      
      wbook.get_sheet(0).write(6, colnum+6, "") 
      wbook.get_sheet(0).write(5, colnum+6, "") 
    wbook.get_sheet(0).write(7, colnum+6, "") 
      #iterate through hour segments for that day      
      for x in parkh[format]: 
       #if regular hours, insert in "HOURS" row      
       if x[0] == 'Park Hours': 
        wbook.get_sheet(0).write(6, colnum+6, x[1]) 
       #if extra magic hours, insert in respective row    
       if x[0] == 'Extra Magic Hours': 
        #insert in morning row         
        if int(x[1][0:1]) in range(2,9): 
         wbook.get_sheet(0).write(5, colnum+6, x[1]) 
        #insert in evening row         
        else: 
         wbook.get_sheet(0).write(7, colnum+6, x[1]) 

     if month == 05: 
      break 

print 'Done editing. Now saving...' 
wbook.save('new.xls') 
print 'new.xls saved' 

Jede Idee, warum könnte es das Jahr werden, ändert sich? Ich habe niemanden gesehen, der anderswo das gleiche Problem hat.

Antwort

1

Sie haben offensichtlich eine Excel-Eingabedatei, die das 1904-Datumssystem verwendet. Ihr sofortiges Problem ist, dass xlutils das Kopieren dieser Dateien nicht korrekt unterstützt. Zum Glück ist das Update ein Einzeiler und Sie können es auch selbst in Ihrem Skript tun, nachdem Sie die Kopie gemacht haben:

wbook = copy(book) 
wbook.dates_1904 = book.datemode 

Dies funktioniert für das Kopieren von Terminen, weil xlwt unterstützt den Satz zu schreiben, der angibt, was datemode in Gebrauch ist .

WARNUNG Alle neuen Datumswerte, die Sie in die Datei schreiben, indem Sie Worksheet.write() wird NICHT korrekt geschrieben werden, wie xlwt leider die ignoriert dates_1904 Einstellung, wenn datetime.date und datetime.datetime Objekte in die Excel-Magie schwebt Umwandlung .

Ich habe einen Fix geschrieben und getestet, der den ganzen Körper der Row.__excel_date_dt Methode ersetzt. Es wird dem neuen xlwt Repository auf github bald verschrieben werden. In der Zwischenzeit hier ist der Code, wenn Sie in Not sind:

def __excel_date_dt(self, date): 
    adj = False 
    if isinstance(date, dt.date): 
     if self.__parent_wb.dates_1904: 
      epoch_tuple = (1904, 1, 1) 
     else: 
      epoch_tuple = (1899, 12, 31) 
      adj = True 
     if isinstance(date, dt.datetime): 
      epoch = dt.datetime(*epoch_tuple) 
     else: 
      epoch = dt.date(*epoch_tuple) 
    else: # it's a datetime.time instance 
     epoch = dt.datetime(1900, 1, 1)    
     date = dt.datetime.combine(epoch, date) 
    delta = date - epoch 
    xldate = delta.days + delta.seconds/86400.0 
    # Add a day for Excel's missing leap day in 1900 
    if adj and xldate > 59: 
     xldate += 1 
    return xldate  

WARNUNG Der Versuch, konvertieren Sie Ihre Datei in das 1900-System nach dem Öffnen in Excel, Haken bei der 1904 Config-Artikel und die Datei Doesn 'T WORK - Termine werden 4 Jahre aus dem Gleichgewicht geraten.

  • öffnen Sie die Datei in Excel, speichern Sie es als XML Spreadsheet 2003 (*.xml) ... dieses Format Aufzeichnungen Daten im Textformat zum Beispiel:

    Was richtig ist dies scheint zu funktionieren 1999-12-31T23:59:59.999

  • die XML-Datei in einem Texteditor öffnen, findet die Zeile, die
    <Date1904/> ... ja liest, die XML gerade aus der Box für Menschen lesbarer ist ... und es löschen, dann speichern die XML-Datei

  • die geänderte XML-Datei in Excel öffnen, werden alle Ihre Daten und Formatierungen
    erhalten bleiben sollte, sollte der einzige Unterschied, dass die lästigen
    1904 Box nicht mehr aktiviert ist. Sie können es dann als XLS-Datei speichern

0

Ich habe dies mit Excel-Arbeitsmappen erlebt, nicht einmal mit Python. Wenn die gleiche Datei zwischen Windows und Mac weitergegeben wird, können seltsame Dinge passieren mit den Daten (obwohl das nicht typisch ist). Excel für Windows verwendet standardmäßig das so genannte "1900" -Datumssystem, während Excel für Mac standardmäßig das Datumssystem "1904" verwendet. (Dies sind die Anfangsjahren für die jeweiligen Systeme.)

Obwohl die xlrd Dokumentation und Quellcode empfehlen dringend, halten Sie mit dem datemode Wert, der in der Arbeitsmappe kodiert wird (wie Sie getan haben), ich denke, es lohnt sich ein Versuch explizit gibt die „anderen“ -Modus xldate_as_tuple zu sehen, ob es das Problem behebt:

year, month, day, hour, minute, second = xlrd.xldate_as_tuple(date, 
    1 - book.datemode) 

datemode0 für 1900-Modus sein, 1 für 1904-Modus; 1 - datemode kippt dies um.

Übrigens können Sie Zeilen ohne Backslash unterbrechen, solange Sie nach einem Komma in einem geklammerten Ausdruck brechen.