2013-07-30 23 views
10

私は、ピボットテーブルXLSXファイルで作業しており、タブごとに新しいファイルを解析するスクリプトを作成しています。openpyxl python3 - 完全な行の書式設定奇妙な動作

openpyxlはデフォルトでピボットテーブルをサポートしていないので、コピー中に失われたピボット 'スタイル'を再挿入する必要があります。

これを行うには、列0の値Totalを探して、各行とcolを繰り返し処理しています。見つかったら、行はすべてbold=Trueに変更されます。

代わりに、最初のNoneの後にすべてのセルを太字にすることがある不規則な動作が発生します。私のprint('bolding totals')メッセージは、それが各行/セルを正しく評価していることを示しています。私は骨頭で、ループの上にインデントをねじ込んでいますか?私は、これはスタイルのopenpyxl取り扱いのバグである疑いがあるこの時点で

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') 

。私は別の非常に簡単な編集を実行し、奇妙な動作をしました。

太字/太字ではない単純なレイアウトのセルがある場合。列全体ではなく、単独のセルの

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

出力の変更: はその後、我々は一つのセルを変更するには、この簡単なコマンドを実行します。

+0

こんにちは、openpyxl' 'のバグは私にとって非常に衝撃的でないと動作するはずです、元のファイルがなければ

。以前はそれに問題がありました。 「openpyxl」を修正するよりも、COMポート経由でExcelを直接使用するようにアプリケーション全体を書き直すほうが簡単でした。私のポストは答えがあります。それが助けて欲しい:http://stackoverflow.com/questions/18145313/openpyxl-highlighting-multiple-cells-when-one-of-them-is-selected-upon-closing-t –

+1

私はこの質問を閉じるために投票していますたとえそれがよく書かれていて興味深いものであっても、(a)答えは受け入れられていないか、そうでなければ、 (b)実際のそして望ましい出力へのリンクが死んでいる。 (c)OPは、ほぼ2年間でSOを訪問していない。 (d)関連するopenpyxlのバグはおそらく今修正されています。 (e)それが今では事実上無回答であるにもかかわらず未解決の質問として現れている。 –

+0

@AleksanderLidtke私はこれに関するバグレポートを覚えていません。あなたのコメントは、openpyxlが私が公正な表現だとは思わない非常にバグがあることを暗示しているようです。もちろん、Excelで直接作業することは可能です。あなたはこれを行うためにxlwingsを見たいかもしれません。 –

答えて

7

openpyxl 2.0以前はセル間でセルスタイルが共有されていました。これはソースXMLのポインタを使用した実装からのホールドオーバーでした.2つ(またはそれ以上)のセルは両方ともスタイル "1"を使用します。 1つのセルのこのスタイルを変更すると、すべてのセルのスタイルが変更されることになります。

これ以降、実装にさまざまな変更が加えられていますが、1つのセルのスタイルを変更するときの副作用はなくなりました。重要な変更点は、Fontなどの書式設定オブジェクトを直接使用できるため、スタイルにラップする必要がないことです。

その他の変更点があります。ワークブックは、親ブックに格納されているデータに依存しているため、ワークブック間でコピーできません。それは確かに難しいですが、次のコードは、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')