今回もエクセル+Pythonです。既存のエクセルファイルに手を加えたい場合があるシーンは多いのではないでしょうか。ということで、今回は既存のエクセルファイルを修正して保存する処理を行っています。処理するエクセルファイルをコマンドラインで指定できるので、シェルスクリプトとの相性もバッチリです。もっともシェルスクリプトを作らなくても必要十分なことが多いかもしれません。

これまでと同様に処理するエクセルデータと実行するPythonスクリプトは同じフォルダ(デスクトップ上にあるsampleフォルダ)にあるものとします。また、保存先のエクセルファイルもsampleフォルダになります。もし、保存先を変えたい場合はスクリプト(プログラム)中のファイルのファイル名(ファイルパス)を変更してください。

また、使用するエクセルファイルは1つのみで以下の内容になっています。シートの数は3つですが、今回のプログラムは複数のシートに対応するようになっていますので、シートの数はいくつあっても問題ありません。

セルの色を指定する

 まずはセルの色を指定してみましょう。これまでと同様にOpenPyXLライブラリを読み込ませます。既存のファイルを読み込ませるのでopenpyxl.load_workbook()の()の中に読み込むエクセルファイルのパス(ファイル名)を指定します。自由にエクセルファイル名(ファイルパス)を指定する方法は最後に説明します。

 セルの塗りつぶし色はopenpyxl.styles.PatternFill()の()の中に色などの必要事項を指定します。

・パターン塗りつぶし(リファレンス)
https://openpyxl.readthedocs.io/en/latest/api/openpyxl.styles.fills.html?highlight=PatternFill

単色で塗る場合はpatternType='solid'として、fgColorで色を指定します。rrggbbの16進数形式で指定します。
以下のプログラムは最初のシートのA1のセルに薄い緑色をつけます。コマンドラインから実行すると修正されたエクセルファイル(data1.xlsx)が作成されます。

import openpyxl
wb = openpyxl.load_workbook('data.xlsx')
ws = wb.worksheets[0]
fcol = openpyxl.styles.PatternFill(patternType='solid', fgColor='88ff88')
ws.cell(1,1).fill = fcol
wb.save('data1.xlsx')

全てのシートの同じ位置のセルの色を指定する

 複数のシートで同じ位置にあるセルの色を変更したい場合もあります。このような場合はシートの数だけforで繰り返しセルの色を変更します。
 以下のプログラムを実行すると全てのシートのA1セルの色が薄い緑色になります。コマンドラインから実行すると修正されたエクセルファイル(data2.xlsx)が作成されます。

import openpyxl
wb = openpyxl.load_workbook('data.xlsx')
ws = wb.worksheets
fcol = openpyxl.styles.PatternFill(patternType='solid', fgColor='88ff88')
for i in ws:
    i.cell(1,1).fill = fcol
wb.save('data2.xlsx')

範囲を指定して色をつける

 一ヶ所でなく複数のセルをまとめてセルの色を指定することもできます。この場合、['A1:M1'][0]のようにセル範囲を指定します。この場合はA1〜M1のセルに色がつきます。['A1:M5'][1]とするとA2〜M2まで、['A1:M5'][2]とするとA3〜M3までのセルに色がつきます。
 以下のプログラムを実行すると全てのシートのA1〜M1セルの色が薄い緑色になります。コマンドラインから実行すると修正されたエクセルファイル(data3.xlsx)が作成されます。

import openpyxl
wb = openpyxl.load_workbook('data.xlsx')
ws = wb.worksheets
fcol = openpyxl.styles.PatternFill(patternType='solid', fgColor='88ff88')
for i in ws:
  for c in i['A1:M1'][0]:
    c.fill = fcol
wb.save('data3.xlsx')

セルに枠をつける

 セルに枠をつけることもできます。まず枠の色は四辺ごと個別に設定できます。ここでは単純に四辺は同じ色にします。枠の幅はstyleの後に以下の種類を指定します。

thin 細い線
medium 普通の線
tick 太い線
double 二重線
hair 細い点線
dotted 点線
dashed 破線
mediumDashed 太い破線
dashDot 一点鎖線
mediumDashDot 太い一点鎖線
dashDotDot 二点鎖線
mediumDashDotDot 太い二点鎖線
slantDashDot 斜めストライプ
・参考(公式サイト) https://openpyxl.readthedocs.io/en/stable/_modules/openpyxl/styles/borders.html

 枠の色はcolorで指定します。RRGGBB形式で指定できます。

Side(style='medium', color='ff0000')

 枠の設定自体は以下のようにします。〜=bのbが設定する枠の種類と色になります。topが上辺、bottomが下辺、leftが左辺、rightが右辺になります。

Border(top=b, bottom=b, left=b, right=b)

 以下のプログラムを実行すると最初のシートのA1セルに赤い枠が追加されます。コマンドラインから実行すると修正されたエクセルファイル(dataB1.xlsx)が作成されます。

import openpyxl
from openpyxl.styles.borders import Border, Side
wb = openpyxl.load_workbook('data.xlsx')
ws = wb.worksheets[0]
b = Side(style='medium', color='ff0000')
bf = Border(top=b, bottom=b, left=b, right=b)
ws.cell(1,1).border = bf
wb.save('dataB1.xlsx')

 全てのワークシートの左上のセルに同じ枠をつけるには以下のようになります。

import openpyxl
from openpyxl.styles.borders import Border, Side
wb = openpyxl.load_workbook('data.xlsx')
ws = wb.worksheets
b = Side(style='medium', color='ff0000')
bf = Border(top=b, bottom=b, left=b, right=b)
for i in ws:
    i.cell(1,1).border = bf
wb.save('dataB2.xlsx')

 1つではなくいくつかのセルに枠をつける場合の方が多いでしょう。その場合は範囲を指定します。全てのワークシートのA1〜M1までのセルに枠をつけるには以下のようになります。

import openpyxl
from openpyxl.styles.borders import Border, Side
wb = openpyxl.load_workbook('data.xlsx')
ws = wb.worksheets
b = Side(style='medium', color='ff0000')
bf = Border(top=b, bottom=b, left=b, right=b)
for i in ws:
  for c in i['A1:M1'][0]:
    c.border = bf
wb.save('dataB3.xlsx')

セルの色と枠を同時に指定する

 今度はすべてのワークシートのセルの色と枠を同時に指定してみます。これまでのをまとめるだけなので難しくはありません。

import openpyxl
from openpyxl.styles.borders import Border, Side
wb = openpyxl.load_workbook('data.xlsx')
ws = wb.worksheets
b = Side(style='medium', color='ff0000')
bf = Border(top=b, bottom=b, left=b, right=b)
fcol = openpyxl.styles.PatternFill(patternType='solid', fgColor='88ff88')
for i in ws:
  for c in i['A1:M1'][0]:
    c.fill = fcol
    c.border = bf
wb.save('dataM1.xlsx')

コマンドラインでエクセルファイルを指定する

 ここまでは処理するエクセルファイルはdata.xlsxで固定されていました。現実的には、これではあまり使い物になりません。処理するファイル名をコマンドラインから指定できれば汎用的になります。コマンドラインからファイル名を指定する方法はすでに説明しましたので詳しくは前々回を参照してください。
 コマンドラインでエクセルファイルを指定できるようにしたプログラムは以下のようになります。コマンドラインで修正・変更するエクセルファイル名(ファイルパス)を指定します。

import sys
import openpyxl
from openpyxl.styles.borders import Border, Side
wb = openpyxl.load_workbook(sys.argv[1])
ws = wb.worksheets
b = Side(style='medium', color='ff0000')
bf = Border(top=b, bottom=b, left=b, right=b)
fcol = openpyxl.styles.PatternFill(patternType='solid', fgColor='88ff88')
for i in ws:
  for c in i['A1:M1'][0]:
    c.fill = fcol
    c.border = bf
wb.save(sys.argv[1])

セルの内容が0なら色を変える

 次にセルの内容に応じてセルの背景色を変えてみます。セルの内容はcellオブジェクトのvalueプロパティで参照できます。0かどうかの判断はifで行います。0は文字列として比較しています。数値として比較する場合はstr()でなくint()やfloat()などを使います。
 実際のプログラムは以下のようになります。コマンドラインでエクセルファイル名を指定するとセルの内容が0の場合のみセルに色が付きます。

import sys
import openpyxl
from openpyxl.styles.borders import Border, Side
wb = openpyxl.load_workbook(sys.argv[1])
ws = wb.worksheets
b = Side(style='medium', color='ff0000')
bf = Border(top=b, bottom=b, left=b, right=b)
fcol = openpyxl.styles.PatternFill(patternType='solid', fgColor='88ff88')
fcol2 = openpyxl.styles.PatternFill(patternType='solid', fgColor='ffffff')
for i in ws:
  for c in i['A1:M4']:
    for cc in c:
      cc.fill = fcol2
      cc.border = bf
      if str(cc.value) == '0':
        cc.fill = fcol
wb.save(sys.argv[1])

 0である場合にフォント(書体)を変えることもできます。from openpyxl.styles import Fontとしてモジュールを読み込んでおきます。セルオブジェクトのfontプロパティにFont(name='Impact',size=18)のように書体名とサイズなどを指定した内容を代入します。データ入力ミスやデータチェックをぱっと見で判断するような場合に便利かもしれません。
 実際のプログラムは以下のようになります。なお、実行結果ですが修正前の内容は先ほどの図と同じなので省略しています。

import sys
import openpyxl
from openpyxl.styles.borders import Border, Side
from openpyxl.styles import Font
wb = openpyxl.load_workbook(sys.argv[1])
ws = wb.worksheets
b = Side(style='medium', color='ff0000')
bf = Border(top=b, bottom=b, left=b, right=b)
fcol = openpyxl.styles.PatternFill(patternType='solid', fgColor='88ff88')
fcol2 = openpyxl.styles.PatternFill(patternType='solid', fgColor='ffffff')
for i in ws:
  for c in i['A1:M4']:
    for cc in c:
      cc.fill = fcol2
      cc.border = bf
      if str(cc.value) == '0':
        cc.fill = fcol
        cc.font = Font(name='Impact',size=18)
wb.save(sys.argv[1])

 フォント(書体)を指定したいけど肝心のフォントの名前がわからない場合もあるかもしれません。そのような場合は以下のプログラムを使えば指定したエクセルファイルのアクティブになっているワークシートのA1セルのフォント名が表示されます。

この記事は
Members+会員の方のみ御覧いただけます

ログイン/無料会員登録

会員サービスの詳細はこちら