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

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

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

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

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Q&A

解決済

5回答

3522閲覧

【VBA】日付ごとのデータで列を作りたい

Jonny_dayo

総合スコア48

VBA

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

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

0グッド

0クリップ

投稿2020/02/02 17:46

編集2020/02/02 22:52

やりたいこと

①元データのA列を2行目から順番に最後までチェックし、重複しているものは無視、していないものは別シートのA1→B1→C1と1行目に入れる
②データ貼り付け先の1行目とコピー元のA列を参照し、一致するものはそのB列のデータをコピー先の一致した列に上から順番に貼り付ける
※日付ごとの列にしたい
イメージ説明

現状

①曜日が入っていると上手く反映されないので消しています

Columns("A:A").Select Selection.Replace What:="(金)", Replacement:=" ", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False Selection.Replace What:="(木)", Replacement:=" ", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False Selection.Replace What:="(土)", Replacement:=" ", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False Selection.Replace What:="(日)", Replacement:=" ", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False Selection.Replace What:="(月)", Replacement:=" ", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False Selection.Replace What:="(火)", Replacement:=" ", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False Selection.Replace What:="(水)", Replacement:=" ", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False

②現状は時間のところに日付をコピペしてB列ごとデータをコピペしているため、日付ごとに対応できてないです

'受付履歴の時間を"データ"シートに保存しておく Range("A2").Copy Range("B1").Select ActiveSheet.Paste Range(Range("B1"), Cells(Rows.count, 2).End(xlUp)).Copy ThisWorkbook.Sheets("データ").Cells(1, Columns.count).End(xlToLeft).Offset(, 1) Next 'ループおわり

困っていること

下のコードでA2以降の重複しない日付を取れるかなと思うのですが、
A列じゃなくてB列から取りたい時はどこをいじればいいのか分からないです(´・ω・`)
また、取ったデータを別シートに貼り付けたい時はどのようにしたら良いのでしょうか…

Dim A As New Collection, i As Long On Error Resume Next For r = 2 To Cells(Rows.count, 1).End(xlUp).Row A.Add Cells(i, 1), Cells(i, 1) Next i

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

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

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

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

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

firstlast

2020/02/02 19:30 編集

VBAを使えば繰り返し処理や条件判断や代入ができますが、質問内容には繰り返しや条件判断の部分が欠落しています。 そういう観点で頭を整理したほうがいいと思います。 そうすれば、質問内容も具体的にかけるようになると思います。
Jonny_dayo

2020/02/02 19:42

回答ありがとうございます! そうですね、すみません混乱したふわっとした質問となっておりました… ①元データのA列を2行目から順番に最後までチェックし、重複しているものは無視、していないものは別シートのA1→B1→C1と1行目に入れていく ②データ貼り付け先の1行目とコピー元のA列を参照し、一致するものはそのB列のデータをコピー先の一致した列に上から順番に貼り付けていく。 やりたいことを具体化するとこんな感じになります!
firstlast

2020/02/02 20:20

やりたいことができないのはどんな障壁があるからでしょうか?
hatena19

2020/02/03 01:28 編集

日付は降順で並んでいるのですか。画像ではそうなってますが、実際のデータも最後まで降順ですか。 日付毎の時刻の重複は排除しなくていいですか。
Jonny_dayo

2020/02/03 01:26

>日付は降順で並んでいるのですか。画像ではそうなってますが、実際のデータも最後まで降順ですか。 はい、実際のデータもこの通りです!
hatena19

2020/02/03 01:31

日付毎の時刻の重複は排除しなくていいですか。
Jonny_dayo

2020/02/03 01:33

直前に以下のコードで時間の重複削除は実行しますので、大丈夫です! Dim A As Long With Range("C9") For A = .CurrentRegion.Rows.count To 1 Step -1 If .Offset(A, 0) = .Offset(A - 1, 0) Then .Offset(A, 0).EntireRow.Delete Next A End With ※実際のデータはC9以下に時間が来るためこのようなコードになっています。
guest

回答5

0

私が作るとこんな感じになります。
※日付の書式が少し違いますが、取り敢えず無視してください。

VBA

1Public Sub xxx() 2 3 Dim sht As Excel.Worksheet 4 5 6 Set sht = ThisWorkbook.Worksheets("Sheet1") 7 8 Dim i As Integer 9 Dim save_date As Date 10 Dim x As Integer 11 i = 1 '左表(コピー元)の行番号 12 x = 4 '右表(コピー先)の列番号 13 14 save_date = DateSerial(2019, 12, 31) '左表の1行目で日付をブレイクさせるため便宜的に任意の日付を代入する。 15 Do Until sht.Cells(i, 1) = "" 'データがなくなったらループを抜ける。 16 temp_date = sht.Cells(i, 1) '左表のカレント行(i行目)の日付を格納する。 17 If temp_date <> save_date Then '左表の日付がブレイクしたら 18 If i > 1 Then x = x + 1 ' 2行目以降でブレイクしたときだけ、右表のコピー先の列を右に1つずらす。 19 sht.Cells(1, x) = temp_date ' 左表の日付を右表の列見出しにコピーする。 20 y = 2 ' 時刻のコピー先を2行目にする。 21 End If 22 23 sht.Cells(y, x) = sht.Cells(i, 2) '左表の時刻(i行2列)を右表(y行x列)にコピーする。 24 y = y + 1 '右表のコピー先の行番号をプラス1する。 25 26 save_date = sht.Cells(i, 1) 'ブレイク判定用 27 i = i + 1 '左の表のコピー元の行番号をプラス1する。 28 Loop 29 30 31 32End Sub

投稿2020/02/03 00:02

firstlast

総合スコア138

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

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

Jonny_dayo

2020/02/03 01:01

回答ありがとうございます! むむむ、自分用に当てはめてみたのですが、何も動かないです… Dim sht As Excel.Worksheet Set sht = ThisWorkbook.Worksheets("コピー元") Dim b As Integer Dim save_date As Date Dim temp_date As Date  '宣言無かったので追記 Dim x As Integer Dim y As Integer      '宣言無かったので追記 b = 9 x = 1 save_date = DateSerial(2019, 12, 31) Do Until sht.Cells(b, 1) = "" temp_date = sht.Cells(b, 1) If temp_date <> save_date Then If b > 1 Then x = x + 1 sht.Cells(1, x) = temp_date y = 2 End If sht.Cells(y, x) = sht.Cells(b, 2) y = y + 1 save_date = sht.Cells(b, 1) b = b + 1 Loop ・loopでのiは他で既に使ってしまったので、bとしました。 ・コピー先のシートの指定はどこでしたら良いのでしょうか?? ・色々他の動きをさせている途中で行いたいのですが、その際はPublic Sub xxx()は取っても大丈夫でしょうか…?
firstlast

2020/02/03 07:20 編集

xxxは仮の名前なので、無視してください。 私が提示したソースコードで注目して欲しいのは、キーブレイクを判定している点と、シートの参照(Cells)、セルの参照と代入(Cells)、条件判断(IF)、繰り返し処理(Loop)です。 コピー先のシートの指定は、 Set sht2 = ThisWorkbook.Worksheets("コピー先") でできます。そのシートのセルに値をコピーするときはsht2.Cells(m, n) = [値] のようにします。 <補足> 私が提示したソースコードは、 キーブレイクを使っているので、左表がキー項目(日付)でソートされている必要があります。あと、重複を排除する処理は含まれていません。 質問内容の「こまっていること」にあるようにコレクションにデータを入れて重複を排除したあとに、そのコレクションの内容をコピー先に代入していく必要があります。
guest

0

出力シートへ逐次データを追記して行くように変えました。

VBA

1Option Explicit 2 3Public Sub 並べ替え() 4 Dim sh1 As Worksheet 5 Dim sh2 As Worksheet 6 Dim sh3 As Worksheet 7 Set sh1 = Worksheets("データ") 8 Set sh2 = Worksheets("作業") 9 Set sh3 = Worksheets("出力") 10 Dim wrow As Long 11 Dim maxrow As Long 12 Dim maxrow2 As Long 13 Dim maxcol2 As Long 14 Dim maxcol3 As Long 15 Dim wrow2 As Long 16 Dim wcol2 As Long 17 Dim wcol3 As Long 18 Dim prevDate As String 19 Dim prevTime As Variant 20 Dim wdate As String 21 Dim wtime As Variant 22 sh2.Cells.ClearContents 23 maxrow = sh1.Cells(Rows.Count, 1).End(xlUp).Row 'データシート 1列目の最終行を求める 24 prevDate = "" 25 wcol2 = 0 26 '作業シートへ転記 27 For wrow = 2 To maxrow 28 wdate = sh1.Cells(wrow, 1).Value 29 wtime = sh1.Cells(wrow, 2).Value 30 If wdate <> prevDate Then 31 wcol2 = wcol2 + 1 32 sh2.Cells(1, wcol2) = Left(wdate, 10) 33 wrow2 = 1 34 prevTime = -1 35 End If 36 If wtime <> prevTime Then 37 wrow2 = wrow2 + 1 38 sh2.Cells(wrow2, wcol2) = wtime 39 End If 40 prevDate = wdate 41 prevTime = wtime 42 Next 43 '出力シートへ転記 44 maxcol2 = sh2.Cells(1, Columns.Count).End(xlToLeft).Column '作業シート 1行目の最終列を求める 45 maxcol3 = sh3.Cells(1, Columns.Count).End(xlToLeft).Column '出力シート 1行目の最終列を求める 46 If sh3.Cells(1, maxcol3).Value = "" Then '最初は1列から出力する為の調整 47 maxcol3 = maxcol3 - 1 48 End If 49 For wcol2 = 1 To maxcol2 50 maxrow2 = sh2.Cells(Rows.Count, wcol2).End(xlUp).Row '作業シート 処理列の最終行を求める 51 wcol3 = maxcol2 - wcol2 + maxcol3 + 1 '出力シートの出力列を算出 52 sh3.Range(sh3.Cells(1, wcol3), sh3.Cells(maxrow2, wcol3)).Value = sh2.Range(sh2.Cells(1, wcol2), sh2.Cells(maxrow2, wcol2)).Value 53 Next 54 MsgBox ("完了") 55End Sub 56

投稿2020/02/04 21:45

tatsu99

総合スコア5470

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

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

0

ベストアンサー

元データのファイルがあれば、確実な結果が保障できますが、
それがないので推定で書きます。
(元データのファイルを https://firestorage.jp/ 等の共有サイトにアップできるならアップしてください。)

元データのシート:データ
作業データのシート:作業
出力先のシート:出力
としています。

VBA

1Option Explicit 2 3Public Sub 並べ替え() 4 Dim sh1 As Worksheet 5 Dim sh2 As Worksheet 6 Dim sh3 As Worksheet 7 Set sh1 = Worksheets("データ") 8 Set sh2 = Worksheets("作業") 9 Set sh3 = Worksheets("出力") 10 Dim wrow As Long 11 Dim maxrow As Long 12 Dim maxrow2 As Long 13 Dim maxcol2 As Long 14 Dim wrow2 As Long 15 Dim wcol2 As Long 16 Dim wcol3 As Long 17 Dim prevDate As String 18 Dim prevTime As Variant 19 Dim wdate As String 20 Dim wtime As Variant 21 sh2.Cells.ClearContents 22 sh3.Cells.ClearContents 23 maxrow = sh1.Cells(Rows.Count, 1).End(xlUp).Row 'データシート 1列目の最終行を求める 24 prevDate = "" 25 wcol2 = 0 26 '作業シートへ転記 27 For wrow = 2 To maxrow 28 wdate = sh1.Cells(wrow, 1).Value 29 wtime = sh1.Cells(wrow, 2).Value 30 If wdate <> prevDate Then 31 wcol2 = wcol2 + 1 32 sh2.Cells(1, wcol2) = Left(wdate, 10) 33 wrow2 = 1 34 prevTime = -1 35 End If 36 If wtime <> prevTime Then 37 wrow2 = wrow2 + 1 38 sh2.Cells(wrow2, wcol2) = wtime 39 End If 40 prevDate = wdate 41 prevTime = wtime 42 Next 43 '出力シートへ転記 44 maxcol2 = sh2.Cells(1, Columns.Count).End(xlToLeft).Column '作業シート 1行目の最終列を求める 45 For wcol3 = 1 To maxcol2 46 maxrow2 = sh2.Cells(Rows.Count, wcol3).End(xlUp).Row '作業シート 処理列の最終行を求める 47 sh3.Range(sh3.Cells(1, maxcol2 - wcol3 + 1), sh3.Cells(maxrow2, maxcol2 - wcol3 + 1)).Value = _ 48 sh2.Range(sh2.Cells(1, wcol3), sh2.Cells(maxrow2, wcol3)).Value 49 Next 50 MsgBox ("完了") 51End Sub 52

実行前のデータのシート及び実行後の出力のシートは、以下の通りです。
実行結果
「出力」シートの1行目の書式設定は日付、2行目以降の書式設定は時刻を設定してください。
(設定値が判らなければその旨補足してください)

投稿2020/02/04 05:50

tatsu99

総合スコア5470

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

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

Jonny_dayo

2020/02/04 16:12

うわあああああああああああああ!!! できたああああああ!!!!!! ありがとうございます!!ありがとうございます!! 他にも回答してくださった皆様本当にありがとうございました!!
Jonny_dayo

2020/02/04 16:33

ベストアンサーに選んだ後からで申し訳ないのですが、、 確認していたところ、シートを読み込むたびにそのデータのみが反映されている気がするのですが、 読み込むたびに「出力」シートの右にどんどん追記されていくようなスタイルにしていくことって可能なのでしょうか?
tatsu99

2020/02/04 21:50

そのような場合は、その旨を質問欄に最初に書くようにしましょう。データを追記する旨が書かれていないので、出力シートを最初にクリアしています。修正版を別回答欄に書きましたので、そちらを参照してください。
Jonny_dayo

2020/02/05 00:31

お手数おかけしました!!! ありがとうございました(´;ω;`)!!
guest

0

ソート機能を使ったやり方で実装してみました。
ソートを使えば貼り付けたい順に並べられるので判定する手間が減るからです。
元のデータを破壊しないようにコピーしてからソートしています。

VBA

1Option Explicit 2 3Public Sub peast() 4 'ダイアログ無視 5 Application.DisplayAlerts = False 6 7 'データシートをコピーしてworkシートを作成する 8 Worksheets("Sheet1").Copy After:=Worksheets(Worksheets.Count) 9 ActiveSheet.Name = "work" 10 11 '最下行取得 12 Dim iMaxRows As Integer 13 iMaxRows = Cells(Rows.Count, 2).End(xlUp).Row 14 15 '日付昇順でソート 16 With Range(Cells(2, 1), Cells(iMaxRows, 2)) 17 .Sort Key1:=.Cells(2, 1), Order1:=xlAscending 18 End With 19 20 '範囲開始行数 21 Dim rbRow As Integer 22 rbRow = 2 23 24 '列インデックス 25 Dim columnIdx As Integer 26 columnIdx = 1 27 28 Dim i As Integer 29 For i = 2 To iMaxRows 30 '次行の日付の値が異なる場合 31 If Cells(i, 1) <> Cells(i + 1, 1) Then 32 With Worksheets("Sheet2") 33 '日付の書式を設定して貼付 34 .Cells(1, columnIdx).NumberFormatLocal = "yyyy/mm/dd(aaa)" 35 .Cells(1, columnIdx).Value = Cells(rbRow, 1).Value 36 '時間の書式を設定して範囲貼付 37 .Range(.Cells(2, columnIdx), .Cells(2 + (i - rbRow), columnIdx)).NumberFormatLocal = "hh:mm:ss" 38 .Range(.Cells(2, columnIdx), .Cells(2 + (i - rbRow), columnIdx)).Value = Range(Cells(rbRow, 2), Cells(i, 2)).Value 39 End With 40 '範囲開始行数に現在行を設定 41 rbRow = i + 1 42 '列インデックスをインクリメント 43 columnIdx = columnIdx + 1 44 End If 45 Next i 46 47 'workシートを削除する 48 Sheets("work").Delete 49 50 '列幅の自動調節 51 Worksheets("Sheet2").Activate 52 Range(Columns(1), Columns(columnIdx)).Columns.AutoFit 53 54 'ダイアログ設定を戻す 55 Application.DisplayAlerts = True 56End Sub

投稿2020/02/03 03:04

編集2020/02/03 03:16
yureighost

総合スコア2183

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

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

0

ExcelVBA

1Sub test() 2 Dim rngData As Range 3 Dim r As Range 4 Dim myColl As New Collection 5 Dim i As Long 6 Dim rngTop As Range 7 8 Set rngData = ActiveSheet.Range("A1").CurrentRegion.Offset(1) 9 With rngData.Cells(1, 1) 10 myColl.Add .Value, .Text 11 Set rngTop = .Offset(, 1) 12 End With 13 14 For Each r In rngData.Row 15 i = myColl.Count 16 On Error Resume Next 17 myColl.Add r.Cells(1).Value, r.Cells(1).Text 18 On Error GoTo 0 19 If i < myColl.Count Then 20 With ActiveSheet.Range("E2") 21 Application.Range(rngTop, r.Cells(0, 2)).Copy .Cells(1, mycol.Count) 22 .Cells(0, 1).Value = myColl(myColl.Count - 1).Value 23 End With 24 set rngtop = r.cells(1,2) 25 End If 26 Next 27End Sub 28

慌てて書いたら不細工になってしまった><
時間が無いので、動作確認してません。
うまくいってないかも^^;
Collectionで重複の排除をされようとしているようなので、
それを使ってみました。
エクセル的にはもっと簡単に書けると思うけど。。。。
興味があればいってくれれば、サンプル書きます。
参考になれば。


小計機能でキーブレークの箇所に小計行を挿入し、
ジャンプ機能で分かれたデータを特定し、
集まり毎に転記するサンプル

ExcelVBA

1Sub test() 2 Dim Rng As Range 3 Dim a As Range 4 Dim i As Long 5 6 'キーブレーク箇所に小計行挿入 7 With Worksheets(1).Cells(1) 8 .Subtotal GroupBy:=1, Function:=xlCount, TotalList:=2 9 With .CurrentRegion 10 Set Rng = Intersect(.Columns(2), .Offset(1)) 11 End With 12 End With 13 14 'キー毎(小計行は数式が入っているので定数のセルだけに特定)にコピペ 15 For Each a In Rng.SpecialCells(xlCellTypeConstants).Areas 16 i = i + 1 17 With Worksheets(2).Cells(1) 18 a.Copy .Cells(2, i) 19 .Cells(1, i).Value = a.Cells(1, 0).Value 20 End With 21 Next 22 23 '小計行削除 24 Rng.CurrentRegion.RemoveSubtotal 25End Sub

必要ならば並び替えも行ってください。
列方向の並び替えもエクセルでできる(はず。)。
個人的にはこっちの方が、考えるのが気楽かな。。。

投稿2020/02/03 00:27

編集2020/02/03 05:17
mattuwan

総合スコア2136

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

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

Jonny_dayo

2020/02/03 01:25

回答ありがとうございます! For Eachは、コレクションオブジェクトまたは配列のみ繰り返しを実行します。 というメッセージが.Rowのところに出て固まってしまいました(´;ω;`) もっと簡単に書けるのが気になるので、お手数ですがサンプル見せてもらうことは可能でしょうか?
mattuwan

2020/02/03 02:34

あああ、失敗>< Collectionなので、 Row → Rows ですね。意味解ります? 簡単にというか、エクセルの機能を一部流用して処理できます。 つまり人が書いたプログラムを使うので、 見た目の行数が減るかなぁ。。。というイメージです。 なのでVB的なロジックとは違う、エクセル的な発想が必要になります。 サンプルは暇を見て。。。
mattuwan

2020/02/03 02:37

あ、あと、サンプルデータは画像ではなく、 テキストで貼り付けていただけると、 コピペが出来て回答側が動作確認しやすいかなと思います。 ここのサイトでどうやったら、簡単に体裁を整えられるか、よくわかってないですが^^;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問