2013-07-30 12 views
10

Pracuję z plikami XLSX z tabelami przestawnymi i piszę skrypt, aby przeanalizować je w nowym pliku na zakładkę.openpyxl python3 - formatowanie całych wierszy wywołuje dziwne zachowanie

Ponieważ openpyxl domyślnie nie obsługuje tabel przestawnych, muszę wykonać pewne prace, aby ponownie wstawić "styl" przestawny podczas kopiowania. Aby to zrobić, Iteruję przez każdy wiersz i col, szukając wartości Total w kolumnie 0. Raz znaleziony wiersz powinien zmienić się na cały bold=True.

Zamiast tego otrzymuję błędne zachowanie, które czasami pogrubia WSZYSTKIE komórki po pierwszym None. Mój komunikat print('bolding totals') pokazuje, że poprawnie ocenia każdy wiersz/komórkę. Czyżbym był zuchwały i skręcał moje wgłębienia na pętlach?

from openpyxl import Workbook 
from openpyxl import load_workbook 
from copy import deepcopy 

wb = load_workbook(filename=r'input.xlsx') 

# Print 1 
sheetlist = wb.get_sheet_names() 
print(sheetlist) 

for i in range(len(sheetlist)-1): 
    dest_filename = r''+sheetlist[i]+'.xlsx' 
    new_wb = Workbook() 
    ws = wb.get_sheet_by_name(sheetlist[i]) 
    new_wb.add_sheet(ws, 0) 

    for k in range(0, new_wb.worksheets[0].get_highest_row()): 
     print(new_wb.worksheets[0].cell(row=k, column=0).value) 
     # ignore empty cells 
     if new_wb.worksheets[0].cell(row=k, column=0).value is not None: 
      if 'Total' in new_wb.worksheets[0].cell(row=k, column=0).value: 
       for j in range(0, new_wb.worksheets[0].get_highest_column()): 
        print('bolding totals, '+str(k), str(j)) 
        new_wb.worksheets[0].cell(
         row=k, column=j).style.font.bold = True 
      elif 'Total' not in new_wb.worksheets[0].cell(row=k, column=0).value: 
       for j in range(0, new_wb.worksheets[0].get_highest_column()): 
        print('not bolding anything') 
        new_wb.worksheets[0].cell(
         row=k, column=j).style.font.bold = False 

    # remove the blank sheet created in new_wb by openpyxl 
    new_wb.remove_sheet(new_wb.get_sheet_by_name('Sheet')) 
    print(new_wb.get_sheet_names()) 
    new_wb.save(dest_filename) 
    break # set to break after one sheet for testing 

print('finished') 

W tym momencie ja podejrzewam, że jest to błąd w obsłudze openpyxl stylach. Przeprowadziłem kolejną bardzo prostą edycję i dostałem dziwne zachowanie.

Jeśli mamy prosty układ z komórkami pogrubionymi/bez wypełnienia. Następnie możemy uruchomić tę prostą komendę zmienić jedną komórkę:

>>> new_wb.worksheets[0].cell(row=10,column=0).style.font.bold = False 

Zmiany wyjścia dla całej kolumny, nie komórka sam.

+0

Cześć, błędy w 'openpyxl' nie są zbyt szokujące dla mnie. Miałem problemy z tym wcześniej. Łatwiej mi było przepisać całą aplikację, aby bezpośrednio używać Excela, poprzez kierowanie go przez porty COM, niż naprawić 'openpyxl'. Oto mój post z odpowiedzią; mam nadzieję, że to pomoże: http://stackoverflow.com/questions/18145313/openpyxl-highlighting-multiple-cells-when-one-of-them-is-selected-upon-closing-t –

+1

Głosuję, aby zamknąć to pytanie , mimo że jest dobrze napisany i interesujący, ponieważ: (a) nie ma żadnych odpowiedzi, akceptowanych lub w inny sposób; (b) linki do faktycznego i pożądanego wyniku są martwe; (c) PO nie odwiedziła SO w ciągu prawie dwóch lat; (d) wszelkie podobne błędy związane z openpyxl zostały prawdopodobnie już naprawione; i (e) nadal pojawia się jako pytanie otwarte, mimo że obecnie jest skutecznie nie do rozstrzygnięcia. –

+0

@AleksanderLidtke Nie pamiętam raportu o błędzie na ten temat. Twój komentarz wydaje się sugerować, że openpyxl jest bardzo błędny, co nie wydaje mi się odpowiednią reprezentacją. Oczywiście, praca bezpośrednio z programem Excel jest świetna, jeśli możesz. Możesz również chcieć spojrzeć na Xlwings, aby to zrobić. –

Odpowiedz

7

Przed wersją Openpyxl 2.0 komórki były współdzielone między komórkami: było to wstrzymanie od implementacji za pomocą wskaźników w źródłowym kodzie XML: dwie (lub więcej) komórek użyłyby stylu "1". Zmiana tego stylu dla jednej komórki oznaczałaby zmianę dla wszystkich komórek, co brzmi jak zachowanie obserwowane tutaj.

Od tego czasu, mimo że nastąpiły różne zmiany w implementacji, nie ma już żadnych skutków ubocznych przy zmianie stylu dla jednej komórki. Ważną zmianą jest to, że obiekty formatujące, takie jak Font, są dostępne bezpośrednio i nie muszą być zawijane w stylu.

Nastąpiło kilka innych zmian: arkusze robocze nie mogą być kopiowane między skoroszytami, ponieważ są zależne od danych przechowywanych w skoroszycie macierzystym.

Bez oryginalnego pliku trudno mieć pewność, ale następujący kod powinien pracować z openpyxl> = 2,2

from openpyxl import Workbook 
from openpyxl import load_workbook 

wb = load_workbook(filename='input.xlsx', read_only=True) 

for sheet in wb.sheetnames: 

    dest_filename = '{0}.xlsx'.format(sheet) 
    new_wb = Workbook() 
    del new_wb["Sheet"] 

    ws1 = wb[sheet] 
    ws2 = new_wb.create_sheet(sheet) 

    for row in ws1: 
     ws2.append([c.value for c in row]) 
     first = row[0] 
     if first.data_type == "s" and "Total" in first.value: 
      for idx in range(len(row)): 
       cell = ws2.cell(row=ws2.max_row, column=idx+1) 
       bolded = cell.font.copy(bold=True) 
       cell.font = bolded 

    new_wb.save(dest_filename) 
    print("saving {0}".format(dest_filename)) 

print('finished')