openpyxlは、拡張子が.xlsx、.xlsmのブックを読み書きできますが、拡張子が.xlsは使用出来ません。また、Excel2010以降のExcelファイルを対象に開発しているので、Excel2007のブックは正常に読み書き出来ない可能性があります。
ブックの操作
ブックの読み込み
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
print(wb.sheetnames)
>>> ['1月売上', '2月売上']
ブックの上書き保存
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#読み込みと同じファイルリンク
wb.save("/Users/TY/Downloads/data/売上データ.xlsx")
ブックの別名で保存
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#読み込みと違うファイルリンク
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
新規フォルダの作成とブック保存
import openpyxl
from pathlib import Path
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#フォルダを作成
Path("NewFolder").mkdir(exist_ok=True)
wb.save("/Users/TY/Downloads/data/NewFolder/売上データ.xlsx")
シートの操作
シートの読み込み
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#インデックス番号で指定
ws1 = wb.worksheets[0]
ws2 = wb.worksheets[1]
print(ws1.title, ws2.title)
>>> 1月売上 2月売上
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#シート名で指定
ws1 = wb["1月売上"]
ws2 = wb["2月売上"]
print(ws1.title, ws2.title)
>>> 1月売上 2月売上
シートの挿入
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
# 先頭のシートに挿入
ws_new1 = wb.create_sheet(index=0)
# 末尾のシートに挿入
ws_new2 = wb.create_sheet()
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
シートの削除
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb.worksheets[0]
#ws = wb["1月売上"]
wb.remove(ws)
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
シート名の変更
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#ws = wb.worksheets[0]
ws = wb["1月売上"]
ws.title = "睦月"
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
シートの移動
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#[-1]で末尾のシートを指定
ws = wb.worksheets[-1]
#ws = wb["2月売上"]
#offsetはマイナスで左、プラスで右に移動
wb.move_sheet(ws, offset=-1)
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
末尾から先頭まで移動する場合は、シートの枚数を計算して移動枚数を決めます。
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#[-1]で末尾のシートを指定
ws = wb.worksheets[-1]
#ws = wb["2月売上"]
end_to_top = 1 - len(wb.worksheets)
wb.move_sheet(ws, offset=end_to_top)
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
シートのコピー(同一ブック内)
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#ws = wb.worksheets[0]
ws = wb["1月売上"]
ws_copy = wb.copy_worksheet(ws)
# シート名変更
ws_copy.title = "1月売上_copy"
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
シートのコピー(新規ブック内)
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
#コピーしたいシート以外は削除
for ws in wb.worksheets:
if ws.title != "1月売上":
wb.remove(ws)
#別名で名前を付けて保存
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
シートの結合(複数ブック)
import openpyxl
from pathlib import Path
# 各ブックの読み込み
wb_list = []
for file in Path("/Users/TY/Downloads/data/NewFolder").glob("*.xlsx"):
wb = openpyxl.load_workbook(file, data_only=True)
wb_list.append(wb)
# 保存先の新しいブック
wb_new = openpyxl.Workbook()
# 1つ目のブックからシート名のリストを取得
sheet_names = wb_list[0].sheetnames
# シート名ごとに処理
for sheet_name in sheet_names:
# このシートに書き込む
ws_new = wb_new.create_sheet(sheet_name)
# 1つ目のブック有無の変数定義
is_first_book = True
# このリストに全ブックから読み取ったデータを格納
row_list = []
# 各ブックごとにデータ読み込み
for wb in wb_list:
# 読み込むシート
ws = wb[sheet_name]
if is_first_book:
start_row = 1
else:
start_row = 2
# シートから1行ずつデータを読み込む
for row in ws.iter_rows(min_row=start_row):
# ヘッダーより下で空欄になったら読み込み終了
if row[0].row > 1 and row[0].value is None:
break
value_list = []
for c in row:
value_list.append(c.value)
row_list.append(value_list)
is_first_book = False
# 書き込み時の行番号
row_num = 1
# シートに1行ずつデータを書き込む
for row in row_list:
# 1行分のデータを書き込む
ws_new.append(row)
# データ部分のA列に日付の表示形式を設定し、F列の数式を書き換え
if row_num > 1:
ws_new.cell(row_num, 2).number_format = "yyyy/m/d"
ws_new.cell(row_num, 6).value = "=D" + str(row_num) + "*E" + str(row_num)
row_num = row_num + 1
# 作成時の既存シートを取り除く
ws_first = wb_new.worksheets[0]
wb_new.remove(ws_first)
wb_new.save("/Users/TY/Downloads/data/NewFolder/売上_merge.xlsx")
セルの操作
セルの指定
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb["1月売上"]
#セル番地で指定
cell_1 = ws["A1"]
print(cell_1.coordinate, cell_1.row, cell_1.column, sep=", ")
>>> A1, 1, 1
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb["1月売上"]
#行列の番号で指定
cell_2 = ws.cell(1, 1)
print(cell_2.coordinate, cell_2.row, cell_2.column, sep=", ")
>>> A1, 1, 1
セルの読み込み
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb["1月売上"]
cell_1 = ws["A4"]
cell_2 = ws["B4"]
cell_3 = ws["C4"]
cell_4 = ws["D4"]
cell_5 = ws["E4"]
cell_6 = ws["F4"]
print(cell_1.value, cell_2.value,cell_3.value, cell_4.value, cell_5.value, cell_6.value, sep=", ")
>>> A社, 2022-01-03 00:00:00, 文具, 800, 7, =D4*E4
日付と数式はExcelのセル表示と違う結果が出力されていることが確認出来ます。
日付が入ったセル:datetime型(日付専用の型)で時刻まで取得される
数式が入ったセル:数式が取得される
data_only = Trueを追加すると、計算結果の数値を取得出来ます。
実際にやってみると、Noneと出力されています。これは、Pythonでブックを保存した場合に起こる現象で、Excelを再度開き直して、手動で保存すれば解消されます。
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx", data_only=True)
ws = wb["1月売上"]
cell_1 = ws["A4"]
cell_2 = ws["B4"]
cell_3 = ws["C4"]
cell_4 = ws["D4"]
cell_5 = ws["E4"]
cell_6 = ws["F4"]
print(cell_1.value, cell_2.value,cell_3.value, cell_4.value, cell_5.value, cell_6.value, sep=", ")
>>> A社, 2022-01-03 00:00:00, 文具, 800, 7, None
該当のExcelブックを開き、手動で保存して閉じる。
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx", data_only=True)
ws = wb["1月売上"]
cell_1 = ws["A4"]
cell_2 = ws["B4"]
cell_3 = ws["C4"]
cell_4 = ws["D4"]
cell_5 = ws["E4"]
cell_6 = ws["F4"]
print(cell_1.value, cell_2.value,cell_3.value, cell_4.value, cell_5.value, cell_6.value, sep=", ")
>>> A社, 2022-01-03 00:00:00, 文具, 800, 7, 5600
数式の値が出力されていることが確認出来ます。
セルに値を入れる
import datetime
dt = datetime.datetime(年, 月, 日, 時, 分, 秒)
import openpyxl
import datetime
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb["1月売上"]
cell_1 = ws["A8"]
cell_1.value = "D社"
cell_2 = ws["B8"]
cell_2.number_format = "yyyy/m/d"
cell_2.value = datetime.datetime(2022, 1, 7)
cell_3 = ws["C8"]
cell_3.value = "玩具"
cell_4 = ws["D8"]
cell_4.value = 1000
cell_5 = ws["E8"]
cell_5.value = 8
cell_6 = ws["F8"]
cell_6.value = "=D8*E8"
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
セルを1行ずつ読み込む
ループ処理をするには、for文を使用します。
for row in ws.iter_rows(min_row=行番号, min_col=列番号):
処理
iter_rows()はデータが入力されている最終行を自動的に認識してそこまで1行ずつ列挙する関数です。そのため、空白であっても書式などが残っていると認識してしまうため、空白があればスキップする処理を追加します。
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb["1月売上"]
for row in ws.iter_rows(min_row=1):
#1列目が空白であればスキップ
if row[0].value is None:
break
#値を格納するための空のリストを作成
value_list = []
#セルの値を1行ずつリストに追加
for cell in row:
value_list.append(cell.value)
print(value_list)
>>>
['会社名', '売上日', '商品名', '単価', '数量', '小計']
['A社', datetime.datetime(2022, 1, 1, 0, 0), 'お菓子', 100, 300, '=D2*E2']
['B社', datetime.datetime(2022, 1, 2, 0, 0), '文具', 500, 4, '=D3*E3']
['A社', datetime.datetime(2022, 1, 3, 0, 0), '文具', 800, 7, '=D4*E4']
['C社', datetime.datetime(2022, 1, 4, 0, 0), 'お菓子', 300, 5, '=D5*E5']
['B社', datetime.datetime(2022, 1, 5, 0, 0), '寝具', 20000, 1, '=D6*E6']
['C社', datetime.datetime(2022, 1, 6, 0, 0), '寝具', 3000, 6, '=D7*E7']
セルに1行ずつ書き込み
import openpyxl
from datetime import datetime
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb["1月売上"]
# 書き込むデータ
data_list = [
["D社",datetime(2022,1,7), "玩具", 250, 10],
["D社",datetime(2022,1,8), "玩具", 50, 6],
["D社",datetime(2022,1,9), "玩具", 300, 4],
]
# 書き込み開始行番号
row_num = 8
for row in data_list:
cell_1 = ws["A" + str(row_num)]
cell_1.value = row[0]
cell_2 = ws["B" + str(row_num)]
cell_2.value = row[1]
cell_2.number_format = "yyyy/m/d"
cell_3 = ws["C" + str(row_num)]
cell_3.value = row[2]
cell_4 = ws["D" + str(row_num)]
cell_4.value = row[3]
cell_5 = ws["E" + str(row_num)]
cell_5.value = row[4]
cell_6 = ws["F" + str(row_num)]
# 数式
c6.value = "=D" + str(row_num) + "*E" + str(row_num)
# 次の行に進む
row_num = row_num + 1
wb.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
応用テクニック
特定の行を除いて、読み込む
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb["1月売上"]
# 全データリスト
data_list = []
for row in ws.iter_rows(min_row=2):
if row[0].value is None:
break
# 何か入力されている行は除外
#if row[4].value is not None:
#単価が1000以上の行は除外
if int(row[3].value) >= 1000:
continue
value_list = []
for cell in row:
value_list.append(cell.value)
data_list.append(value_list)
# 確認
for data in data_list:
print(data)
>>>
['A社', datetime.datetime(2022, 1, 1, 0, 0), 'お菓子', 100, 300, '=D2*E2']
['B社', datetime.datetime(2022, 1, 2, 0, 0), '文具', 500, 4, '=D3*E3']
['A社', datetime.datetime(2022, 1, 3, 0, 0), '文具', 800, 7, '=D4*E4']
['C社', datetime.datetime(2022, 1, 4, 0, 0), 'お菓子', 300, 5, '=D5*E5']
条件に一致する行の抽出
import openpyxl
wb = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws = wb["1月売上"]
# 全データリスト
data_list = []
for row in ws.iter_rows(min_row=2):
if row[0].value is None:
break
value_list = []
for cell in row:
value_list.append(cell.value)
data_list.append(value_list)
# 検索結果リスト
target_list = []
# 顧客の検索
for data in data_list:
# 先頭検索条件:会社名がAから始まる(末尾検索:endswitch)
if data[0].startswith("A"):
target_list.append(data)
# 確認
for target in target_list:
print(target)
>>>
['A社', datetime.datetime(2022, 1, 1, 0, 0), 'お菓子', 100, 300, '=D2*E2']
['A社', datetime.datetime(2022, 1, 3, 0, 0), '文具', 800, 7, '=D4*E4']
別ブックから条件に合うデータを転記
import openpyxl
# マスタのブック、シート
wb_master = openpyxl.load_workbook("/Users/TY/Downloads/data/会社所在.xlsx")
ws_master = wb_master["所在地"]
# 売上データのブック、シート
wb_data = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws_data = wb_data["1月売上"]
# マスタの全データリスト
data_list = []
for row in ws_master.iter_rows(min_row=2):
if row[0].value is None:
break
value_list = []
for cell in row:
value_list.append(cell.value)
data_list.append(value_list)
# データ行番号
row_num = 1
# 列名追加
ws_data["G" + str(row_num)].value = "所在地"
# データを1行ずつ処理
for row in ws_data.iter_rows(min_row=2):
row_num = row_num + 1
# 転記先の会社名「A列」
data_id = row[0].value
# 検索
for data in data_list:
# 検索条件(転記元の会社名=転記先の会社名)
if data[0] == data_id:
# 転記元の所在地を転記先の「G列」に追加
ws_data["G" + str(row_num)].value = data[1]
break
# 別名で保存
wb_data.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
条件毎にシートを分けして転記
import openpyxl
# マスタのブック、シート
wb_master = openpyxl.load_workbook("/Users/TY/Downloads/data/会社所在.xlsx")
ws_master = wb_master["所在地"]
# 売上データのブック、シート
wb_data = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx", data_only=True)
ws_data = wb_data["1月売上"]
# マスタの全データリスト
data_list = []
for row in ws_master.iter_rows(min_row=2):
if row[0].value is None:
break
value_list = []
for cell in row:
value_list.append(cell.value)
data_list.append(value_list)
# 会社名ごとに処理
for data in data_list:
data_id = data[0]
data_name = data[1]
# データの検索
data_list = []
for row in ws_data.iter_rows(min_row=2):
value_list = []
for cell in row:
value_list.append(cell.value)
# 検索条件
if value_list[0] == data_id:
data_list.append(value_list)
if len(data_list) > 0:
# 会社名をシート名にしてシート追加
ws_new = wb_data.create_sheet(title=data_name)
# ヘッダー書き込み
ws_new.append(["会社名","売上日","商品名","単価","数量","小計"])
# データ書き込み
row_num = 2
for data in data_list:
ws_new.append(data)
ws_new.cell(row_num,2).number_format = "yyyy/m/d"
row_num = row_num + 1
# 別ブックで保存
wb_data.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
条件毎に集計(件数)
import openpyxl
# マスタのブック、シート
wb_master = openpyxl.load_workbook("/Users/TY/Downloads/data/会社所在.xlsx")
ws_master = wb_master["所在地"]
# データのブック、シート
wb_data = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx")
ws_data = wb_data["1月売上"]
# マスタの全データリスト
data_list = []
for row in ws_master.iter_rows(min_row=2):
if row[0].value is None:
break
value_list = []
for cell in row:
value_list.append(cell.value)
data_list.append(value_list)
# 集計結果を入れるリスト
result_list = []
# 顧客ごとに処理
for data in data_list:
data_id = data[0]
data_name = data[1]
# 売上件数のカウント
count_sales = 0
# 売上データの検索
for row in ws_data.iter_rows(min_row=2):
# 検索条件
if row[0].value == data_id:
count_sales = count_sales + 1
if count_sales > 0:
# 会社名、売上日、売上件数の3項目を追加
result_list.append([data_id, data_name, count_sales])
# 集計結果用シートを追加
ws_new = wb_data.create_sheet(title="売上件数")
# ヘッダー書き込み
ws_new.append(["会社名","売上日","売上件数"])
# 集計結果書き込み
for result in result_list:
ws_new.append(result)
# 別名で保存
wb_data.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")
条件毎に集計(金額)
import openpyxl
# マスタのブック、シート
wb_master = openpyxl.load_workbook("/Users/TY/Downloads/data/会社所在.xlsx")
ws_master = wb_master["所在地"]
# データのブック、シート
wb_data = openpyxl.load_workbook("/Users/TY/Downloads/data/売上データ.xlsx", data_only=True)
ws_data = wb_data["1月売上"]
# マスタの全データリスト
data_list = []
for row in ws_master.iter_rows(min_row=2):
if row[0].value is None:
break
value_list = []
for cell in row:
value_list.append(cell.value)
data_list.append(value_list)
# 集計結果を入れるリスト
result_list = []
# 条件ごとに処理
for data in data_list:
data_id = data[0]
data_name = data[1]
# 売上の集計
sum_sales = 0
# 売上データの検索
for row in ws_data.iter_rows(min_row=2):
# 検索条件
if row[0].value == data_id:
# 売上の額は「F列(インデックス=5)」
sum_sales = sum_sales + row[5].value
if sum_sales > 0:
# 会社名、売上日、売上合計の3項目を追加
result_list.append([data_id, data_name, sum_sales])
# 集計結果用シートを追加
ws_new = wb_data.create_sheet(title="売上別")
# ヘッダー書き込み
ws_new.append(["会社名","売上日","売上計"])
# 集計結果書き込み
for result in result_list:
ws_new.append(result)
# 別名で保存
wb_data.save("/Users/TY/Downloads/data/更新_売上データ.xlsx")