『マクロで、範囲を指定し、全体的に移動させたい。』(ひまぞう)
下記でつまずいており、ご教示いただけますと幸いです。
ルール
・移動範囲:C列からの数値のみ(最後列と最後行は、都度変動)
・A列とB列の2つの条件で開始行を検索
・移動指示数が1の場合、1行下に範囲全体を移動
・余白となった開始行は0と入力
・処理方法は、1指示1処理で完了(次は、逆移動を交え複数指示をしたいため)
悩み
複数指示実行時、最下行の累積管理で計3行となるべきが、2行しか表示されません。
使用シート
1.「指示」シート
日付 区分 移動数
2025/3/1 A 1
2025/3/2 A 2
2.「集計」シート」
日付 区分 品番1 品番2 試作
2025/3/1 A 20 40 0
2025/3/1 B 20 40 0
2025/3/1 C 20 40 0
2025/3/2 A 20 40 10
2025/3/2 B 20 40 0
2025/3/2 C 20 40 0
◇指示が、2025/3/1 A 1 の場合
・移動 C2:E7→C3:E8
・移動後の開始行に0入力 C2:E2
日付 区分 品番1 品番2 試作
2025/3/1 A 0 0 0
2025/3/1 B 20 40 0
2025/3/1 C 20 40 0
2025/3/2 A 20 40 0
2025/3/2 B 20 40 10
2025/3/2 C 20 40 0
20 40 0
◇指示が、複数の場合、2025/3/1 A 1と、2025/3/2 A 2
日付 区分 品番1 品番2 試作
2025/3/1 A 0 0 0
2025/3/1 B 20 40 0
2025/3/1 C 20 40 0
2025/3/2 A 0 0 0
2025/3/2 B 0 0 0
2025/3/2 C 20 40 0
20 40 10 20 40 0 20 40 0
< 使用 Excel:Excel2019、使用 OS:Windows11 >
こういうことですか?
Sub test() Dim c(1) As Range, r As Range, x Set c(0) = Sheets("指示").[a1].CurrentRegion.Offset(1) Set c(1) = Sheets("集計").[a1].CurrentRegion For Each r In c(0).Columns(1).Cells If r <> "" Then x = c(0).Parent.Evaluate("match(" & r.Address & "&""|""&" & _ r(, 2).Address & "," & c(1).Columns(1).Address(, , , 1) & _ "&""|""&" & c(1).Columns(2).Address(, , , 1) & ",0)") If IsNumeric(x) Then With c(1)(x, 3).Resize(r(, 3), 3) .Insert xlShiftDown .Offset(-r(, 3)).Value = 0 End With End If End If Next End Sub (jindon) 2025/04/29(火) 13:39:15
少々、配列や開始行、シート名は違うのですが、作成中のコードがなぜ正しく処理できないかを、ご教示いただくことはできますでしょうか。
使用シート
1.「スライド指示」シート
ヘッダー:7行目
指示行:8:16行目
日付 タクト スライド数
2025/3/1 A 1
2025/3/2 A 2
2.「スライド調整後」シート」
ヘッダー:5行目
データ:6行目から
日付 タクト 納場 品番1 品番2 試作 (D列から数値)
このコードには、移動処理とは別に、戻し処理の2つの処理が入っております。
最終的には、この2つの処理を複数で同時に行いたいのですが、片方が出来ればその片方が崩れるのイタチごっこで悩んでおります。
ちなみに、戻しのルールは、指示数の入力をマイナスとし、開始行で下行を上詰めし合計。そして、範囲全体を上に移動となります。
◇戻し指示が、2025/3/2 A -1 の場合
日付 区分 品番1 品番2 試作
2025/3/1 A 20 40 0
2025/3/1 B 20 40 0
2025/3/1 C 20 40 0
2025/3/2 A 40 80 10
2025/3/2 B 20 40 0
2025/3/2 C 20 40 0
2025/3/3 A 20 40 0
2025/3/3 B 0 0 0
Sub Slide_Both_Main()
Dim ws指示 As Worksheet Dim ws調整後 As Worksheet Set ws指示 = Worksheets("スライド指示") Set ws調整後 = Worksheets("スライド調整後")
Dim i As Long i = 8 ' 指示は8行目からスタート
Do While ws指示.Cells(i, 1).Value <> "" Slide_OneShot i i = i + 1 Loop
' すべての指示を処理した後、罫線を引き直す Dim 最終行 As Long, 最終列 As Long 最終列 = ws調整後.Cells(6, Columns.count).End(xlToLeft).Column 最終行 = ws調整後.Cells(ws調整後.Rows.count, 1).End(xlUp).Row
With ws調整後.Range(ws調整後.Cells(7, 4), ws調整後.Cells(最終行, 最終列)).Borders .LineStyle = xlContinuous .Weight = xlThin End With
MsgBox "すべてのスライド指示が完了しました!", vbInformation
End Sub
Sub Slide_OneShot(i指示 As Long)
Dim ws指示 As Worksheet, ws調整後 As Worksheet Set ws指示 = Worksheets("スライド指示") Set ws調整後 = Worksheets("スライド調整後")
Dim j As Long, col As Long Dim 指示日 As Date, 指示タクト As String, スライド数 As Long Dim 最終行 As Long, 最終列 As Long, 対象行 As Long
最終列 = ws調整後.Cells(6, Columns.count).End(xlToLeft).Column スライド数 = ws指示.Cells(i指示, 3).Value
Dim tmp As Variant tmp = ws指示.Cells(i指示, 1).Value If IsDate(tmp) Then 指示日 = CDate(tmp) Else MsgBox "指示日の形式が正しくありません。", vbExclamation Exit Sub End If
指示タクト = ws指示.Cells(i指示, 2).Value
最終行 = ws調整後.Cells(ws調整後.Rows.count, 1).End(xlUp).Row 対象行 = 0
For j = 6 To 最終行 If ws調整後.Cells(j, 1).Value = 指示日 And ws調整後.Cells(j, 2).Value = 指示タクト Then 対象行 = j Exit For End If Next j
If 対象行 = 0 Then Exit Sub
If スライド数 > 0 Then ' --- 後ろ倒し --- Dim 移動データ As Variant 移動データ = ws調整後.Range(ws調整後.Cells(対象行, 4), ws調整後.Cells(最終行, 最終列)).Value
ws調整後.Range(ws調整後.Cells(対象行 + スライド数, 4), ws調整後.Cells(最終行 + スライド数, 最終列)).Value = 移動データ
ws調整後.Range(ws調整後.Cells(対象行, 4), ws調整後.Cells(対象行 + スライド数 - 1, 最終列)).Value = 0
ElseIf スライド数 < 0 Then ' --- 戻し --- Dim 合計配列() As Double ReDim 合計配列(1 To 最終列 - 3)
Dim k As Long For k = 0 To Abs(スライド数) For col = 4 To 最終列 合計配列(col - 3) = 合計配列(col - 3) + ws調整後.Cells(対象行 + k, col).Value Next col Next k
For col = 4 To 最終列 ws調整後.Cells(対象行, col).Value = 合計配列(col - 3) Next col
For k = 1 To Abs(スライド数) For col = 4 To 最終列 ws調整後.Cells(対象行 + k, col).ClearContents Next col Next k
Dim 詰め行差 As Long: 詰め行差 = Abs(スライド数) Dim 最終データ行 As Long 最終データ行 = ws調整後.Cells(ws調整後.Rows.count, 1).End(xlUp).Row
For j = 対象行 + 詰め行差 + 1 To 最終データ行 For col = 4 To 最終列 ws調整後.Cells(j - 詰め行差, col).Value = ws調整後.Cells(j, col).Value ws調整後.Cells(j, col).ClearContents Next col Next j
End If
End Sub
(ひまぞう) 2025/04/29(火) 14:48:49
>ちなみに、戻しのルールは、指示数の入力をマイナスとし、開始行で下行を上詰めし合計。そして、範囲全体を上に移動となります
もし開始行で既に調整がある場合ですか? 即ち、開始行から指定行数の値が全て0の場合のみ実行ですか?
ここが理解できません。 (jindon) 2025/04/29(火) 15:56:00
指示
・2025/3/1 A 2
・2025/3/2 A -2
日付 タクト 品番1 品番2 試作
2025/3/1 A 0 0
2025/3/1 B 0 0
2025/3/1 C 20 40
2025/3/1 D 20 40
2025/3/2 A 60 120
2025/3/2 B 20 40
2025/3/2 C 20 40 10
2025/3/2 D 20 40
0 0 0 0
(ひまぞう) 2025/04/29(火) 16:26:10
少々混乱しています。
2025/3/1 D 20 40 2025/3/2 D 20 40 が2行追加されていますが、間違いないですか?
もし間違いなければその理由を説明してください。
(jindon) 2025/04/29(火) 17:11:07
>2025/04/29(火) 14:48:49 のひまぞうさんの表にはDがありません。
どのような理由で2025/04/29(火) 16:26:10の表でdが追加されるのわかりません。
あくまでも、同じ表が結果の表に変換されるのですよね?
そうでなければ、ちんぷんかんぷんになりますよ? (jindon) 2025/04/29(火) 17:57:42
ですから、変換の過程で追加するならその条件の説明が無ければ無理です。
2025/04/29(火) 14:48:49で提示された表がどのようにして2025/04/29(火) 16:26:10の表に変換するのか 詳しく説明してください。
1) 2025/3/1 A 1 の場合どのようにならなければならないのか
2) 2025/3/2 A -2 の場合
3) どの段階でDの行が挿入されるのか。
等々... (jindon) 2025/04/29(火) 18:40:01
1つのブックに使用するマクロは2つあります。
・マクロ1は作成済
・今回マクロ2を作成したいと考えております。
マクロ処理
・マクロ1は、加工前データとして「スライド調整後」シートに展開。
・加工前データをそのまま使用し、マクロ2で「スライド指示」を実行し「スライド調整後」シートの加工前データを変更。
・どの段階でDの行が挿入されるのか。
データはすべて、マクロ1が実行された初めの時点となります。(途中から追加する事はございません)
マクロ1実行後
「スライド調整後」シート
加工前データ
日付 タクト 納場 A1 A2 A3 A4 A5 試作
2025/3/1 A A80 20 30 40 50 60 0
2025/3/1 B A80 20 30 40 50 60 0
2025/3/1 C A80 20 30 40 50 60 0
2025/3/1 D A80 20 30 40 50 60 0
2025/3/2 A A80 20 30 40 50 60 0
2025/3/2 B A80 20 30 40 50 60 0
2025/3/2 C A80 20 30 40 50 60 0
2025/3/2 D A80 20 30 40 50 60 0
マクロ2実行後
1)2025/3/1 A 1 の場合
・対象行のD列から最後列の数値を全体的に1行下げる。
・対象行のD列から最後列に0入力
日付 タクト 納場 A1 A2 A3 A4 A5 試作
2025/3/1 A A80 0 0 0 0 0 0
2025/3/1 B A80 20 30 40 50 60 0
2025/3/1 C A80 20 30 40 50 60 0
2025/3/1 D A80 20 30 40 50 60 0
2025/3/2 A A80 20 30 40 50 60 0
2025/3/2 B A80 20 30 40 50 60 0
2025/3/2 C A80 20 30 40 50 60 0
2025/3/2 D A80 20 30 40 50 60 0
20 30 40 50 60 0
2) 2025/3/2 A -2 の場合 ・対象行で合計処理(合計は計3行)(対象行+下2行) ・合計後、最下行から2行詰め上げ(ブランクとなった最後行はそのままクリア)
日付 タクト 納場 A1 A2 A3 A4 A5 試作
2025/3/1 A A80 20 30 40 50 60 0
2025/3/1 B A80 20 30 40 50 60 0
2025/3/1 C A80 20 30 40 50 60 0
2025/3/1 D A80 20 30 40 50 60 0
2025/3/2 A A80 60 90 120 150 180 0
2025/3/2 B A80 20 30 40 50 60 0
2025/3/2 C A80
2025/3/2 D A80
3) 複数指示、1と-2の場合(2025/3/1 A 1,2025/3/2 A -2)
日付 タクト 納場 A1 A2 A3 A4 A5 試作
2025/3/1 A A80 0 0 0 0 0 0
2025/3/1 B A80 20 30 40 50 60 0
2025/3/1 C A80 20 30 40 50 60 0
2025/3/1 D A80 20 30 40 50 60 0
2025/3/2 A A80 60 90 120 150 180 0
2025/3/2 B A80 20 30 40 50 60 0
2025/3/2 C A80 20 30 40 50 60 0
2025/3/2 D A80
3) 複数指示、2と-2の場合(2025/3/1 A 2,2025/3/2 A -2)
日付 タクト 納場 A1 A2 A3 A4 A5 試作
2025/3/1 A A80 0 0 0 0 0 0
2025/3/1 B A80 0 0 0 0 0 0
2025/3/1 C A80 20 30 40 50 60 0
2025/3/1 D A80 20 30 40 50 60 0
2025/3/2 A A80 60 90 120 150 180 0
2025/3/2 B A80 20 30 40 50 60 0
2025/3/2 C A80 20 30 40 50 60 0
2025/3/2 D A80 20 30 40 50 60 0
(ひまぞう) 2025/04/29(火) 20:25:14
有難うございます。 全て理解できました。
以下で試してください。 もし全てのケースでの結果が良ければ、コードに付いて知りたい部分があれば質問してください。
私は、質問が無ければ全て理解したものと判断しますので。
Sub test() Dim c(1) As Range, r As Range, x, i&, mySum#(), t& Set c(0) = Sheets("スライド指示").[a7].CurrentRegion.Offset(1) Set c(1) = Sheets("スライド調整後").[a5].CurrentRegion t = c(1).Columns.Columns.Count - 3 ReDim mySum(1 To t) For Each r In c(0).Columns(1).Cells If r <> "" Then x = c(0).Parent.Evaluate("match(" & r.Address & "&""|""&" & _ r(, 2).Address & "," & c(1).Columns(1).Address(, , , 1) & _ "&""|""&" & c(1).Columns(2).Address(, , , 1) & ",0)") If IsNumeric(x) Then If r(, 3) > 0 Then With c(1)(x, 4).Resize(r(, 3), t) .Insert xlShiftDown .Offset(-r(, 3)).Value = 0 End With Else For i = 1 To t mySum(i) = Application.Sum(c(1)(x, i + 3).Resize(Abs(r(, 3)) + 1)) Next c(1)(x, 4).Resize(, t) = mySum c(1)(x + 1, 4).Resize(Abs(r(, 3)), t).Delete xlShiftUp End If End If End If Next End Sub (jindon) 2025/04/29(火) 21:06:05
作っていただいたコードを拝見し、とてもシンプルで驚きました。特に、データの検索とか行の操作、あと戻し処理の後の詰め込みが、あんなに簡単にできるなんてビックリでした。
ただ、一つだけ追加のお願いがありまして…
処理後に、対象行のみJ列に「0」が入力されるようになっています。もし可能でしたら、この処理を見直して頂くことはできますでしょうか。
(ひまぞう) 2025/04/30(水) 09:53:00
期待通りの動作を確認できほっとしました。
>対象行のみJ列に「0」が入力されるようになっています。 こちらでは再現できませんので、おそらくCurrentRegionの範囲がJ列まで取得されているのでしょう。
2行挿入してください。
Set c(1) = Sheets("スライド調整後").[a5].CurrentRegion x = c(1).Parent.Evaluate(Replace("max(if(#=""試作"",column(#)))", "#", c(1).Address)) '<---1 Set c(1) = c(1).Resize(, x) '<---2 t = c(1).Columns.Columns.Count - 3
"試作"を探してその列までで限定します。 (jindon) 2025/04/30(水) 10:35:13
不思議です。
こちらで試したのはJ4に何かしらの値(スペースとか)を入力して確認しましたがOKでした。 もしかしたら 他の[試作] がCurrentRegionの他行のJ列に存在しているとしか考えられません。
範囲をA:I に決め打ちで良いのなら 挿入した2行を削除して
Set c(1) = Sheets("スライド調整後").[a5].CurrentRegion を Set c(1) = Sheets("スライド調整後").[a5].CurrentRegion.Resize(, 9) に変更してください。 (jindon) 2025/04/30(水) 12:28:09
また何かあったら頼らせてもらうかもしれませんが、その時はぜひ力を貸してください。
改めて、この度はありがとうございました。
(ひまぞう) 2025/04/30(水) 14:42:34
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.