質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.32%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

1回答

349閲覧

商品毎に転記するVBAを、グループ毎に転記できるように改良したい。

ATSUHAYAshi

総合スコア1

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2025/02/02 14:06

編集2025/02/04 14:14

実現したいこと

“商品別売上日報EEMMDD”より、商品毎に集計シートへ転記する、既存のVBAをグループ毎に集計シートへ転記するように改良したい。
イメージ説明
イメージ説明
イメージ説明
イメージ説明
イメージ説明

発生している問題・分からないこと

指定した複数行を、横並びではなく縦1列で貼り付ける方法

該当のソースコード

Sub CopyDataToSummary() Dim wbSummary As Workbook Dim wsTranscribe As Worksheet Dim wsBalance As Worksheet Dim folderPath As String Dim fileName As String 'Dim dateToFind As String Dim dateToFind As Date Dim foundDate As Range ' 日報集計ブックを設定 Set wbSummary = ThisWorkbook Set wsTranscribe = wbSummary.Sheets("転記") '日付を取得 dateToFind = wsTranscribe.Range("C3").Value Debug.Print dateToFind ' 指定されたフォルダ内のファイルを検索 folderPath = "H:\XXXXX\★AAAAAAA\BBBBBBBB\CC商品別売上日報 生データ" ' フォルダのパスを指定 fileName = Dir(folderPath & "\商品別売上日報" & Format(dateToFind, "eemmdd")& ".xlsx") Debug.Print folderPath Debug.Print fileName ' ファイルが見つかった場合 If fileName <> "" Then 'ブックを開く Set wb = Workbooks.Open(folderPath & "\" & fileName) Set wsBalance = Worksheets("商品別売上日報(当日・前月)") wsBalance.Select ' 商品別売上日報(当日・前月)をコピーして貼付け CopyAndPasteData wsBalance.Range("F8:F28"),wbSummary.Sheets("商品A"), dateToFind CopyAndPasteData wsBalance.Range("G8:G28"),wbSummary.Sheets("商品B"), dateToFind CopyAndPasteData wsBalance.Range("J8:J28"),wbSummary.Sheets("商品C"), dateToFind CopyAndPasteData wsBalance.Range("K8:K28"),wbSummary.Sheets("商品D"), dateToFind CopyAndPasteData wsBalance.Range("L8:L28"),wbSummary.Sheets("商品E"), dateToFind CopyAndPasteData wsBalance.Range("N8:N28"),wbSummary.Sheets("商品F"), dateToFind CopyAndPasteData wsBalance.Range("O8:O28"),wbSummary.Sheets("商品G"), dateToFind CopyAndPasteData wsBalance.Range("P8:P28"),wbSummary.Sheets("商品H"), dateToFind CopyAndPasteData wsBalance.Range("Q8:Q28"),wbSummary.Sheets("商品I"), dateToFind CopyAndPasteData wsBalance.Range("R8:R28"),wbSummary.Sheets("商品J), dateToFind CopyAndPasteData wsBalance.Range("T8:T28"),wbSummary.Sheets("商品K"), dateToFind CopyAndPasteData wsBalance.Range("W8:W28"),wbSummary.Sheets("商品L"), dateToFind CopyAndPasteData wsBalance.Range("X8:X28"),wbSummary.Sheets("商品M"), dateToFind CopyAndPasteData wsBalance.Range("Y8:Y28"),wbSummary.Sheets("商品N"), dateToFind 'ブックを閉じる ActiveWorkbook.Close Else MsgBox "指定された日付の残高日報が見つかりませんでした。" End If End Sub Sub CopyAndPasteData(rngSource As Range, wsTarget As Worksheet, dateToFind As Date) Dim cell As Range Dim rngTarget As Range Dim wrng As Range Set rngTarget = Nothing For Each wrng In wsTarget.Range("F1:Z1,F25:Z25,F49:Z49,F73:Z73,F97:Z97,F121:Z121") If wrng.Value = dateToFind Then Set rngTarget = wrng Exit For End If Next If Not rngTarget Is Nothing Then '貼り付ける rngSource.Copy wsTarget.Cells(rngTarget.Row + rngSource.Row - rngSource.Cells(0, 1).Row, rngTarget.Column).PasteSpecial Paste:=xlPasteValues Application.CutCopyMode = False End If End Sub

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

wsBalance.Range("F8:F28")をwsBalance.Range("R8:R28,F8:F28")とすることで、指定した列をコピーすることは出来るが、貼り付けると2列で配置されるので、これを1列にして貼り付けたい。
また商品と商品の間には、スペース(前月比などがエクセル関数で入ってる)があるので、そのスペースに影響が出ないようにする必要もある。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sk.exe

2025/02/03 01:34 編集

> グループ毎に集計シートへ転記する > 指定した商品グループ毎に、シートへ転記 ・[商品グループ]はどのようにして定義されているのか。 ・それぞれの[商品]はどの[商品グループ]に属しているのか  (何を以てそれを判別するのか)。 ・全ての[商品グループ]のマスタや全ての[商品]のマスタに相当するリストは  どこに、どのようにして定義されているのか。  (そもそもそんなリストは存在しないのか) 以上の 3 点が不明なので、現時点では回答のしようがありません。 > 実際の日報は、商品は15種。 添付画像で例示された内容に照らし合わせるなら、 "商品グループ1"に含まれるのが"商品A"と"商品D"、 "商品グループ2"に含まれるのが"商品B"と"商品E"と"商品H"、 "商品グループ3"に含まれるのが"商品F"と"商品C" というところまでは読み取れますが、残りの 8 商品がそれぞれどの[商品グループ]に含まれるのかが判りません。 また"商品グループ3"に属する商品については、日報ファイル上での並び順と集計シート上の並び順が一致していないようですが、[商品グループ](集計シート)ごとに定められた任意の並び順に入れ替える形でデータを出力する必要があるのでしょうか。
ATSUHAYAshi

2025/02/04 14:30

既存のコードに商品A~Nとあるのは、既存のコードではグループを考える必要がなかった為、 実際は、同じ商品の個人向け、法人向けでグループがあり、個人向け商品の中で、商品Cグループ、Dグループがあります。 商品Aは、法人向けのみなのでグループなし。 商品Bは、法人向け、個人向けでの1つのグループ 商品Cは、個人向け(3商品)で1つのグループ 商品Dは、個人向け(2商品)で1つのグループになっています。
logres_Fan

2025/02/04 15:27

日報シートのセルを参照するように集計シートを作れば終わる仕事じゃないの?
sk.exe

2025/02/05 02:47

追記された説明を拝見した限り、「既存のマクロを改良する」より「既存のマクロとは別に新しいマクロを作成する」方がよいと思います。 例示されたように「複数ある貼り付け先シートの構造が統一されていない」 「コピー元/貼り付け先となるセル領域の捉え方が商品によって大きく異なる」 「一部の商品については例外的な(Y28セルの)コピー/貼り付け処理が発生する」 ということなら、少なくとも CopyAndPasteData のような共通化ルーチンに置き換えるのは無理筋です。 それぞれの商品(貼り付け先シート)に合わせた制御フローを個別に検討されることをお奨めします。 ワークシート[範囲]の C3 セルの値に応じて動的に変更されるべきなのは「コピー元となるブックのパス」と「貼り付け先となる範囲の列位置」のみであり、それ以外の要素についてはほぼ決め打ちでよいはずです。
guest

回答1

0

既存のマクロとは別に新しいマクロを作成する

とりあえず、追記された説明の通りの処理を実行される場合のサンプルを例示します。

vba

1Sub CopyDataToSummary2() 2 3 Dim wbSummary As Workbook 4 Dim wsTranscribe As Worksheet 5 6 Set wbSummary = ThisWorkbook 7 Set wsTranscribe = wbSummary.Worksheets("転記") 8 9 'C3セルの値が日時データではない場合 10 If IsDate(wsTranscribe.Range("C3").Value) = False Then 11 wbSummary.Activate 12 wsTranscribe.Select 13 wsTranscribe.Range("C3").Select 14 MsgBox "集計対象となる日付を入力してください。", _ 15 vbExclamation, _ 16 "入力エラー" 17 Set wsTranscribe = Nothing 18 Set wbSummary = Nothing 19 Exit Sub 20 End If 21 22 Dim dateToFind As Date 23 Dim folderPath As String 24 Dim fileName As String 25 26 '参照対象となる日報の日付を取得 27 dateToFind = wsTranscribe.Range("C3").Value 28 Debug.Print dateToFind 29 30 '日報ブックが保存されているフォルダのパスを指定 31 folderPath = "H:\XXXXX\★AAAAAAA\BBBBBBBB\CC商品別売上日報 生データ" 32 Debug.Print folderPath 33 34 'フォルダが見つからなかった場合 35 If Dir(folderPath, vbDirectory) = "" Then 36 MsgBox "パス""" & fileName & """に該当するフォルダが見つかりません。", _ 37 vbExclamation, _ 38 "フォルダ参照エラー" 39 Set wsTranscribe = Nothing 40 Set wbSummary = Nothing 41 Exit Sub 42 End If 43 44 '対象日付に該当する日報ブックのファイルパスを生成 45 fileName = folderPath & "\商品別売上日報" & Format(dateToFind, "eemmdd") & ".xlsx" 46 Debug.Print fileName 47 48 'ファイルが見つからなかった場合 49 If Dir(fileName) = "" Then 50 MsgBox "パス""" & fileName & """に該当するブックが見つかりません。", _ 51 vbExclamation, _ 52 "ファイル参照エラー" 53 Set wsTranscribe = Nothing 54 Set wbSummary = Nothing 55 Exit Sub 56 End If 57 58 Dim wbDailyReport As Workbook 59 Dim wsBalance As Worksheet 60 61 '日報ブックを開いて参照 62 Set wbDailyReport = Workbooks.Open(fileName) 63 '日報シートを参照 64 Set wsBalance = wbDailyReport.Worksheets("商品別売上日報(当日・前月)") 65 66 Dim rngDestinationHeader As Range 67 Dim rngFoundCell As Range 68 Dim headerFirstColumn As String 69 Dim headerColumnSize As Long 70 Dim balanceFirstDataRow As Long 71 Dim dataRowSize As Long 72 73 '集計シート上の日付ヘッダーの最初の列位置 74 headerFirstColumn = "F" 75 '集計シート上の日付ヘッダーの列数 76 headerColumnSize = 21 77 '日報シートの先頭のデータ行の行番号 78 balanceFirstDataRow = 8 79 'データ行の行数 80 dataRowSize = 21 81 82 'ワークシート[商品A]を集計シートとして以下の処理を実行 83 With wbSummary.Worksheets("商品A") 84 '3行目を基点としてヘッダー範囲を参照 85 Set rngDestinationHeader = .Cells(3, headerFirstColumn).Resize(1, headerColumnSize) 86 'ヘッダー範囲から対象日付に該当するセルを検索 87 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 88 'ヒットした場合 89 If Not rngFoundCell Is Nothing Then 90 '日報シートのU列のデータ行の値を集計シートの該当列のデータ行に複写 91 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "U"), rngFoundCell.Offset(1, 0), dataRowSize 92 End If 93 Set rngFoundCell = Nothing 94 Set rngDestinationHeader = Nothing 95 96 End With 97 98 'ワークシート[商品B]を集計シートとして以下の処理を実行 99 With wbSummary.Worksheets("商品B") 100 101 '3行目を基点としてヘッダー範囲を参照 102 Set rngDestinationHeader = .Cells(3, headerFirstColumn).Resize(1, headerColumnSize) 103 'ヘッダー範囲から対象日付に該当するセルを検索 104 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 105 'ヒットした場合 106 If Not rngFoundCell Is Nothing Then 107 '日報シートのM列のデータ行の値を集計シートの該当列のデータ行に複写 108 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "M"), rngFoundCell.Offset(1, 0), dataRowSize 109 End If 110 Set rngFoundCell = Nothing 111 Set rngDestinationHeader = Nothing 112 113 '27行目を基点としてヘッダー範囲を参照 114 Set rngDestinationHeader = .Cells(27, headerFirstColumn).Resize(1, headerColumnSize) 115 'ヘッダー範囲から対象日付に該当するセルを検索 116 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 117 'ヒットした場合 118 If Not rngFoundCell Is Nothing Then 119 '日報シートのV列のデータ行の値を集計シートの該当列のデータ行に複写 120 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "V"), rngFoundCell.Offset(1, 0), dataRowSize 121 End If 122 Set rngFoundCell = Nothing 123 Set rngDestinationHeader = Nothing 124 125 End With 126 127 'ワークシート[商品C_個人向け]を集計シートとして以下の処理を実行 128 With wbSummary.Worksheets("商品C_個人向け") 129 130 '3行目を基点としてヘッダー範囲を参照 131 Set rngDestinationHeader = .Cells(3, headerFirstColumn).Resize(1, headerColumnSize) 132 'ヘッダー範囲から対象日付に該当するセルを検索 133 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 134 'ヒットした場合 135 If Not rngFoundCell Is Nothing Then 136 '日報シートのO列のデータ行の値を集計シートの該当列のデータ行に複写 137 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "O"), rngFoundCell.Offset(1, 0), dataRowSize 138 End If 139 Set rngFoundCell = Nothing 140 Set rngDestinationHeader = Nothing 141 142 '27行目を基点としてヘッダー範囲を参照 143 Set rngDestinationHeader = .Cells(27, headerFirstColumn).Resize(1, headerColumnSize) 144 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 145 'ヒットした場合 146 If Not rngFoundCell Is Nothing Then 147 '日報シートのP列のデータ行の値を集計シートの該当列のデータ行に複写 148 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "P"), rngFoundCell.Offset(1, 0), dataRowSize 149 End If 150 Set rngFoundCell = Nothing 151 Set rngDestinationHeader = Nothing 152 153 '51行目を基点としてヘッダー範囲を参照 154 Set rngDestinationHeader = .Cells(51, headerFirstColumn).Resize(1, headerColumnSize) 155 'ヘッダー範囲から対象日付に該当するセルを検索 156 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 157 'ヒットした場合 158 If Not rngFoundCell Is Nothing Then 159 '日報シートのQ列のデータ行の値を集計シートの該当列のデータ行に複写 160 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "Q"), rngFoundCell.Offset(1, 0), dataRowSize 161 End If 162 Set rngFoundCell = Nothing 163 Set rngDestinationHeader = Nothing 164 165 End With 166 167 'ワークシート[商品C_法人向け]を集計シートとして以下の処理を実行 168 With wbSummary.Worksheets("商品C_法人向け") 169 170 '3行目を基点としてヘッダー範囲を参照 171 Set rngDestinationHeader = .Cells(3, headerFirstColumn).Resize(1, headerColumnSize) 172 'ヘッダー範囲から対象日付に該当するセルを検索 173 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 174 'ヒットした場合 175 If Not rngFoundCell Is Nothing Then 176 '日報シートのW列のデータ行の値を集計シートの該当列のデータ行に複写 177 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "W"), rngFoundCell.Offset(1, 0), dataRowSize 178 179 '例外的な代入処理 180 '日報シートのY28セルの値を集計シートの該当列の74行目のセルに代入 181 .Cells(74, rngFoundCell.Column).Value = wsBalance.Range("Y28").Value 182 183 End If 184 Set rngFoundCell = Nothing 185 Set rngDestinationHeader = Nothing 186 187 End With 188 189 'ワークシート[商品D_個人向け]を集計シートとして以下の処理を実行 190 With wbSummary.Worksheets("商品D_個人向け") 191 192 '3行目を基点としてヘッダー範囲を参照 193 Set rngDestinationHeader = .Cells(3, headerFirstColumn).Resize(1, headerColumnSize) 194 'ヘッダー範囲から対象日付に該当するセルを検索 195 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 196 'ヒットした場合 197 If Not rngFoundCell Is Nothing Then 198 '日報シートのR列のデータ行の値を集計シートの該当列のデータ行に複写 199 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "R"), rngFoundCell.Offset(1, 0), dataRowSize 200 End If 201 Set rngFoundCell = Nothing 202 Set rngDestinationHeader = Nothing 203 204 '27行目を基点としてヘッダー範囲を参照 205 Set rngDestinationHeader = .Cells(27, headerFirstColumn).Resize(1, headerColumnSize) 206 'ヘッダー範囲から対象日付に該当するセルを検索 207 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 208 'ヒットした場合 209 If Not rngFoundCell Is Nothing Then 210 '日報シートのS列のデータ行の値を集計シートの該当列のデータ行に複写 211 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "S"), rngFoundCell.Offset(1, 0), dataRowSize 212 End If 213 Set rngFoundCell = Nothing 214 Set rngDestinationHeader = Nothing 215 216 End With 217 218 'ワークシート[商品D_法人向け]を集計シートとして以下の処理を実行 219 With wbSummary.Worksheets("商品D_法人向け") 220 221 '3行目を基点としてヘッダー範囲を参照 222 Set rngDestinationHeader = .Cells(3, headerFirstColumn).Resize(1, headerColumnSize) 223 'ヘッダー範囲から対象日付に該当するセルを検索 224 Set rngFoundCell = FindDateFromHeader(rngDestinationHeader, dateToFind) 225 'ヒットした場合 226 If Not rngFoundCell Is Nothing Then 227 '日報シートのX列のデータ行の値を集計シートの該当列のデータ行に複写 228 CopyColumnValues wsBalance.Cells(balanceFirstDataRow, "X"), rngFoundCell.Offset(1, 0), dataRowSize 229 End If 230 Set rngFoundCell = Nothing 231 Set rngDestinationHeader = Nothing 232 233 End With 234 235 '日報ブックを閉じる 236 Set wsBalance = Nothing 237 wbDailyReport.Close False 238 Set wbDailyReport = Nothing 239 240 With wbSummary.Worksheets("商品A") 241 .Select 242 .Cells(3, headerFirstColumn).Select 243 End With 244 245 Set wsTranscribe = Nothing 246 Set wbSummary = Nothing 247 248 MsgBox "複写処理が完了しました。", _ 249 vbInformation, _ 250 "実行完了" 251 252End Sub 253 254'該当日付列の検索処理 255Private Function FindDateFromHeader(Header As Range, FindDate As Date) As Range 256 257 If Header Is Nothing Then 258 Exit Function 259 End If 260 261 Dim rngLoop As Range 262 263 For Each rngLoop In Header.Cells 264 If rngLoop.Value = FindDate Then 265 Set FindDateFromHeader = rngLoop 266 Exit Function 267 End If 268 Next 269 270End Function 271 272'データ複写用処理 273Private Sub CopyColumnValues(SourceTopCell As Range, DestinationTopCell As Range, RowSize As Long) 274 275 If SourceTopCell Is Nothing Then 276 Exit Sub 277 End If 278 279 If DestinationTopCell Is Nothing Then 280 Exit Sub 281 End If 282 283 Dim rngSource As Range 284 Dim rngDestination As Range 285 286 Set rngSource = SourceTopCell.Resize(RowSize, 1) 287 Set rngDestination = DestinationTopCell.Resize(RowSize, 1) 288 289 rngDestination.Value = rngSource.Value 290 291 Set rngSource = Nothing 292 Set rngDestination = Nothing 293 294End Sub

投稿2025/02/05 06:10

編集2025/02/05 07:44
sk.exe

総合スコア1014

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.32%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問