marron_117
@marron_117

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Pythonでエクセルファイルの内容を別のエクセルファイルにコピー&ペーストしたい

Q&A

Closed

Pythonでエクセルのファイルを二つ読み込み、データの一部ををコピー&ペーストしたい

ここに解決したい内容を記載してください。

Pythonで以下のプログラムを書こうと考えています。
1 業界名を入力
2 データ_業界名のエクセルを読み込む
3 AとBの列を記入しているところまで読み込む
4 A2からデータのないセルまで以下を繰り返す
  ・A列にある名前と同じ名前のエクセルファイルを開く
  ・B列と同じ日付があった場合、該当セルの一つ下から二つ上まで行ごとコピーする
  ・データ_業界名のエクセルの企業名のシートにペーストする。
  ・もし前の行にデータがある場合は一行開けてペーストする
5 A2からデータのないセルまで以下を繰り返す
  ・A列にある名前と同じ名前のシートに移動する。
  ・B~H、J、K、M列を削除する。

うまく文字で伝えることができないので、写真をつけて説明します。
IMG_0421.jpg
IMG_0418.jpg
IMG_0422.jpg
IMG_0423.jpg
IMG_0420.jpg

実行したプログラム

chatGPTを使用して書いてもらったプログラムが以下になります。

quiita.py
import openpyxl
from google.colab import drive
from openpyxl.styles import Alignment

# Google ドライブをマウント
drive.mount('/content/drive')

# 入力内容:業界名の入力
industry_name = input("業界名を入力してください: ")

# Google ドライブ上の特許価値ファイルのパス
drive_file_path = '/content/drive/My Drive/特許価値_{}.xlsx'.format(industry_name)

# 特許価値のエクセルファイル読み込み
patent_excel = openpyxl.load_workbook(drive_file_path)
patent_sheet = patent_excel.active

# 企業名と日付データを読み込む
data = []
for row in patent_sheet.iter_rows(min_row=2, max_col=2, values_only=True):
    data.append((row[0], row[1]))

# エクセルファイルの処理
for company_name, date_str in data:
    company_excel_name = '{}.xlsx'.format(company_name)
    company_excel_path = '/content/drive/My Drive/{}'.format(company_excel_name)

    try:
        company_excel = openpyxl.load_workbook(company_excel_path)
        print('{} のエクセルファイルを開きました。'.format(company_excel_name))
    except FileNotFoundError:
        print('{} のエクセルファイルが見つかりません。'.format(company_excel_name))
        continue

    company_sheet = company_excel.active

    for row in company_sheet.iter_rows(min_row=2, max_col=2, values_only=True):
        if row[0] == date_str:
            start_row = company_sheet.max_row - company_sheet.min_row + 1
            end_row = start_row + 1
            while company_sheet.cell(row=end_row, column=1).value is not None:
                end_row += 1

            new_row = [date_str] + list(row[1:])

            if company_name not in patent_excel.sheetnames:
                patent_sheet = patent_excel.create_sheet(title=company_name)
                patent_sheet.append(['日付'] + [chr(i) for i in range(66, 82)])  # BからPまでの列を追加
            else:
                patent_sheet = patent_excel[company_name]

            for col_idx, value in enumerate(new_row, start=1):
                patent_sheet.cell(row=patent_sheet.max_row + 1, column=col_idx, value=value)
                patent_sheet.cell(row=patent_sheet.max_row, column=col_idx).alignment = Alignment(horizontal='center')

            patent_excel.save(drive_file_path)
            break

    company_excel.close()

# シートの削除と整形
for company_name, _ in data:
    company_excel_name = '{}.xlsx'.format(company_name)
    try:
        company_excel = openpyxl.load_workbook('/content/drive/My Drive/{}'.format(company_excel_name))
    except FileNotFoundError:
        continue

    company_sheet = company_excel.active

    if company_name in company_excel.sheetnames:
        company_sheet = company_excel[company_name]
        company_sheet.delete_cols(2, 8)  # BからH、J、K、Mまでの列を削除
        company_excel.save('/content/drive/My Drive/{}'.format(company_excel_name))

    company_excel.close()

print('処理が完了しました。')

実行後

これを実行することはできました。しかし、上記で書いたプログラムの流れの4と5、写真で言うと2枚目からが成功できていないのか、データファイルを確認すると何も変わっていません。どのように変更すればデータをコピーして貼り付けることができるのか教えていただきたいです。

追記

どこが動いているか確認するため間にprintを入れて確認したところ、ファイルを開いた後からシートの削除と整形をするまで何も動いておらず、すぐにファイルを閉じてしまっていました。

1

2Answer

どのように変更すればデータをコピーして貼り付けることができるのか教えていただきたいです。

質問の回答ではないですが、問題のある箇所を見つけるためにもデバッグをしてみるといいと思います。

1Like

やりたことが明確のようですし、Excelに閉じた操作ならば、VBAで書く方が楽かと思います。
(お望みであれば、VBAコードを指南します)
Pythonにこだわる理由があれば別ですが・・・

1Like

Comments

  1. @marron_117

    Questioner

    Pythonへのこだわりはありません。指南いただけると幸いです。

  2. @marron_117

    Questioner

    chatgptを用いてvbaで書いてみたのですがこのようになりました。

    Sub データコピーと整形()
    
        Dim wsSource As Worksheet
        Dim srcRow As Long
        Dim targetFile As String
        Dim industryName As String
        Dim wb As Workbook
        Dim ws As Worksheet
        
        ' ソースファイルを設定(既に開いているものとします)
        Set wsSource = ThisWorkbook.Sheets("株価チャート") ' ソースファイルのシート名を指定
        
        ' 「業界名」を入力
        industryName = InputBox("業界名を入力してください:", "業界名の入力")
        If industryName = "" Then Exit Sub ' キャンセルが選択された場合、処理終了
        
        srcRow = 2 ' ソースファイルの開始行を指定
        
        ' ターゲットファイルを設定
        targetFile = Environ("USERPROFILE") & "\Desktop\" & industryName & "\" & "特許価値_" & industryName & ".xlsx" ' ユーザーデスクトップのパスに保存
        
        ' ターゲットファイルを開く
        Set wb = Workbooks.Open(targetFile)
        
        ' A2からデータのないセルまで繰り返し
        Do Until wsSource.Cells(srcRow, 1).Value = ""
            ' A列の名前と同じ名前のエクセルファイルを開く
            On Error Resume Next
            Set ws = wb.Sheets(wsSource.Cells(srcRow, 1).Value)
            On Error GoTo 0
            
            If Not ws Is Nothing Then
                ' B列内のセル内容と一致した場合、該当セルの一つ下から二つ上までの行をコピー
                If ws.Cells(1, 2).Value = wsSource.Cells(srcRow, 2).Value Then
                    wsSource.Cells(srcRow - 2, 1).Resize(3, wsSource.Cells(srcRow, Columns.Count).End(xlToLeft).Column).Copy
                    ws.Cells(1, 1).Insert xlShiftDown ' データがある場合は1行開けてペースト
                End If
            End If
            
            srcRow = srcRow + 1 ' 次の行に移動
        Loop
        
        ' ターゲットファイルを保存
        wb.Save
        wb.Close
        
        ' ターゲットファイルを再度開く
        Set wb = Workbooks.Open(targetFile)
        
        ' A2からデータのないセルまで繰り返し
        srcRow = 2 ' ソースファイルの開始行を再設定
        Do Until wsSource.Cells(srcRow, 1).Value = ""
            ' A列の名前と同じ名前のシートに移動
            On Error Resume Next
            Set ws = wb.Sheets(wsSource.Cells(srcRow, 1).Value)
            On Error GoTo 0
            
            ' B列からH列、J列、K列、M列を削除
            If Not ws Is Nothing Then
                ws.Range("B:H,J:J,K:K,M:M").Delete Shift:=xlToLeft
            End If
            
            srcRow = srcRow + 1 ' 次の行に移動
        Loop
        
        ' ターゲットファイルを再度保存
        wb.Save
        wb.Close
    
    End Sub
    
    

    これで行うとファイルが存在するはずの場所を指定しているにもかかわらず、ファイルが存在しないと言われてしまいます。ファイル名を日本語ではなくローマ字などに変えた方がいいでしょうか?

  3. 赤字のコメントを理解して使ってください。

    ex1.png

    以下、VBAコード(自分の環境で動作確認済み)
    (Microsoft 365 Excel for Mac version 16.76 (23081101))
    OSに依存するコードはないので、Windowsでも動くはずです

    Sub example()
    
        Application.ScreenUpdating = False
    
        Dim srcRow As Long
        Dim myPath As String, myDir As String, mySheet As Worksheet
        Set mySheet = ThisWorkbook.ActiveSheet
        myPath = ThisWorkbook.FullName
        myDir = Left(myPath, Len(myPath) - Len(ThisWorkbook.Name))
        
        srcRow = 2
        Do While (Not IsEmpty(Cells(srcRow, 1))) And (Not IsEmpty(Cells(srcRow, 2)))
            Dim company As String, companySheet As Worksheet
            company = Cells(srcRow, 1)
            Dim tagetPath As String
            tagetPath = myDir & company & ".xlsx"
            
            Set companySheet = ThisWorkbook.Sheets.Add(After:=ActiveWorkbook.Worksheets(ActiveWorkbook.Worksheets.Count))
            ActiveSheet.Name = company
            
            Dim targetBook As Workbook
            Set targetBook = Application.Workbooks.Open(FileName:=tagetPath, ReadOnly:=True, UpdateLinks:=False)
        
            Dim r As Variant, r0 As Variant: r = r0
            On Error Resume Next
            r = Application.WorksheetFunction.Match(mySheet.Cells(srcRow, 2), targetBook.ActiveSheet.Columns(1), 0)
            On Error GoTo 0
            If IsEmpty(r) Then
                companySheet.Cells(1, 1) = "not found same date!"
    
            Else
                Dim row As Integer: row = CInt(r)
                With targetBook.ActiveSheet
                    .Range(.Rows(row - 2), .Rows(row + 1)).Copy
                End With
                companySheet.Activate
                ActiveSheet.Cells(1, 1).Select
                ActiveSheet.Paste
                Application.CutCopyMode = False
                
                ActiveSheet.Range("B:H,J:K,M:M").Delete Shift:=xlToLeft
            End If
            
            targetBook.Close savechanges:=False
            mySheet.Activate
            srcRow = srcRow + 1
        Loop
    
        Application.ScreenUpdating = True
    
    End Sub
    
  4. @marron_117

    Questioner

    返事が遅くなり申し訳ございません。動くことができました。ありがとうございます!

  5. お役に立ててよかったです☺️

Your answer might help someone💌