Option Explicit
Const Folder1 As String = "d:\goo\data10\IN" '転記元ブック格納フォルダ
Const Folder2 As String = "d:\goo\data10\OUT" '転記先ブック格納フォルダ
Const Book2 As String = "★【PGB】2024~2029年度 電源国内_PGB 投資予測_帳票"
Dim RE As Object '正規表現オブジェクト
Dim ks1 As Worksheet '管理シート
Dim ks2 As Worksheet '変換結果シート
Dim k_maxrow1 As Long '管理シート最大行番号
Dim k_maxrow2 As Long '変換結果シート最大行番号
Dim ows1 As Worksheet '投資用シート
Dim ows2 As Worksheet '計上用シート
Dim dicT As Object 'ディクショナリ キー:装置名 値:予測の行番号
Public Sub 月度対応転記()
Dim krow1 As Long '管理シート行番号
Dim sname As String '装置名称
Dim bname As String
Dim bname2 As String '転記先ブック名
Dim bpath2 As String '転記先ブックのパス名
Dim wb1 As Workbook '転記元ブック
Dim wb2 As Workbook '転記先ブック
Dim out_mm As Long '出力月数
Application.ScreenUpdating = False
Set dicT = CreateObject("Scripting.Dictionary")
Set RE = CreateObject("VBScript.RegExp")
RE.Pattern = "^\d{4}/\d{2}$"
RE.Global = True
Set ks1 = Worksheets("管理")
Set ks2 = Worksheets("変換結果")
out_mm = 0
If IsNumeric(ks1.Range("E2").Value) = True Then
out_mm = CLng(ks1.Range("E2").Value)
End If
If out_mm < 1 Or out_mm > 12 Then
MsgBox ("管理シートの出力月が不正です")
Exit Sub
End If
k_maxrow2 = 2
'転記先ブックオープン
bname2 = Book2 & ".xlsx"
bpath2 = Folder2 & "\" & bname2
Set wb2 = Workbooks.Open(bpath2)
Set ows1 = wb2.Worksheets("国内_連結修正後")
Set ows2 = wb2.Worksheets("国内_計上連結修正後")
'投資用シート、計上用シート読込
If check_out_sheet() = False Then Exit Sub
'管理シート読込及び転記先名称のチェック
k_maxrow1 = ks1.Cells(Rows.Count, "A").End(xlUp).Row
For krow1 = 2 To k_maxrow1
sname = ks1.Cells(krow1, "B").Value
If dicT(sname) = False Then
MsgBox ("管理シートの[" & sname & "]は転記先シートに存在しません")
Exit Sub
End If
Next
'転記元ブックの読込
bname = Dir(Folder1 & "\*.xlsx")
Application.Calculation = xlCalculationManual
Do While bname <> ""
Set wb1 = Workbooks.Open(Folder1 & "\" & bname)
If read_all_sheets(wb1) = False Then
Application.Calculation = xlCalculationAutomatic
Exit Sub
End If
wb1.Close
bname = Dir()
Loop
'転記先ブックの名称を変えて保存する
Application.Calculation = xlCalculationAutomatic
bname2 = Book2 & "_" & out_mm & "月予測.xlsx"
bpath2 = Folder2 & "\" & bname2
Application.DisplayAlerts = False
wb2.SaveAs (bpath2)
Application.DisplayAlerts = True
wb2.Close
Application.ScreenUpdating = True
MsgBox ("完了")
End Sub
'転記先ブックのシートチェック
Private Function check_out_sheet() As Boolean
Dim eflag As Boolean: eflag = False
Dim maxrow1 As Long
Dim maxrow2 As Long
check_out_sheet = False
maxrow1 = ows1.Cells(Rows.Count, "C").End(xlUp).Row
maxrow2 = ows2.Cells(Rows.Count, "C").End(xlUp).Row
If maxrow1 <> maxrow2 Then
MsgBox ("転記先ブックの2つのシートの行数が不一致です")
Exit Function
End If
If maxrow1 < 6 Then eflag = True
If (maxrow1 - 2) Mod 4 <> 0 Then eflag = True
If eflag = True Then
MsgBox ("転記先ブックの2つのシートの行数が正しくありません")
Exit Function
End If
Dim wrow As Long
Dim key1 As String
Dim key2 As String
For wrow = 3 To maxrow1 Step 4
key1 = ows1.Cells(wrow, "B").Value
key2 = ows2.Cells(wrow, "B").Value
If key1 <> key2 Then
MsgBox ("転記先ブックの2つのシートの装置名の並びが不一致です")
Exit Function
End If
dicT(key1) = wrow + 2 '予測の行を設定
Next
check_out_sheet = True
End Function
'転記元の全シートを処理する
Private Function read_all_sheets(ByRef wb1 As Workbook) As Boolean
read_all_sheets = False
Dim sarray As Variant
Dim elm As Variant
Dim result As Boolean
'処理対象となるシートの一覧
sarray = Array("D6110", "D6120", "D6125", "D6560")
For Each elm In sarray
If exist_sheet(wb1, elm) = True Then
result = read_1_sheet(wb1, elm)
If result = False Then Exit Function
End If
Next
read_all_sheets = True
End Function
'指定シートがブック内にあるかチェックする
Private Function exist_sheet(ByRef wb1, ByVal elm As String)
Dim i As Long
exist_sheet = False
For i = 1 To wb1.Worksheets.Count
If UCase(elm) = UCase(wb1.Worksheets(i).Name) Then
exist_sheet = True
Exit Function
End If
Next
End Function
'1シートを処理する
Private Function read_1_sheet(ByRef wb1, ByVal elm As String)
Dim ws As Worksheet
Dim maxrow As Long
Dim wrow As Long
Dim wmonth As String
Dim sname As String
Dim t_mm As Long
Dim k_mm As Long
Dim tk_row As Long
Dim t_col As Long
Dim k_col As Long
read_1_sheet = False
Set ws = wb1.Worksheets(elm)
maxrow = ws.Cells(Rows.Count, "A").End(xlUp).Row
For wrow = 2 To maxrow
'投資月チェック
wmonth = ws.Cells(wrow, "C").Value
t_mm = get_month(wmonth)
If t_mm = 0 Then
ws.Activate
ws.Cells(wrow, "C").Select
MsgBox ("転記元シート[" & elm & "]投資月エラー:" & wmonth)
Exit Function
End If
'計上月チェック
wmonth = ws.Cells(wrow, "D").Value
k_mm = get_month(wmonth)
If k_mm = 0 Then
ws.Activate
ws.Cells(wrow, "D").Select
MsgBox ("転記元シート[" & elm & "]計上月エラー:" & wmonth)
Exit Function
End If
'装置名チェック
sname = ws.Cells(wrow, "B").Value
If dicT.exists(sname) = False Then
sname = get_sname(ws.Cells(wrow, "A").Value)
End If
'転記先の装置名が存在する場合
If sname <> "" Then
tk_row = dicT(sname)
t_col = get_column(t_mm)
k_col = get_column(k_mm)
ows1.Cells(tk_row, t_col).Value = ws.Cells(wrow, "E").Value '投資用金額
ows2.Cells(tk_row, k_col).Value = ws.Cells(wrow, "E").Value '計上用金額
End If
Next
read_1_sheet = True
End Function
'月の取得 yyyy/mm からmmの数値を取得(0はエラー)
Private Function get_month(ByVal wmonth) As Long
get_month = 0
Dim w_mm As Long
If RE.test(wmonth) = False Then Exit Function
w_mm = CLng(Right(wmonth, 2))
If w_mm < 1 Or w_mm > 12 Then Exit Function
get_month = w_mm
End Function
'管理番号から転記先の装置名を取得する
Private Function get_sname(ByVal kbango As String)
Dim ptn As String
Dim wrow As Long
For wrow = 2 To k_maxrow1
ptn = ks1.Cells(wrow, "A").Value
If kbango Like ptn Then
get_sname = ks1.Cells(wrow, "B").Value
ks2.Cells(k_maxrow2, "A").Value = kbango
ks2.Cells(k_maxrow2, "B").Value = ptn
ks2.Cells(k_maxrow2, "C").Value = ks1.Cells(wrow, "B").Value
k_maxrow2 = k_maxrow2 + 1
Exit Function
End If
Next
get_sname = ""
End Function
'月数からカラム番号を取得する
Private Function get_column(ByVal mm As Long) As Long
Dim bias As Long: bias = 1
If mm < 4 Then mm = mm + 12
If mm > 9 Then bias = bias + 1
get_column = mm + bias
End Function