月日のシートタブを使って順番に並び替える方法

このQ&Aのポイント
  • VBAを使用して、ワークシートのタブにある日付のシートタブを指定の順番に並び替える方法を教えてください。
  • シートタブの名前に含まれる月の文字位置を検索し、月の数値を取得し、年度と組み合わせて日付に変換する方法を試しました。
  • しかし、日付関数を使用した配列の並び替えやワークシートの移動など、実装には困難があります。お手伝いいただけると幸いです。
回答を見る
  • ベストアンサー

月日のシートタブを使って,順番に並び替える方法?

こんにちは,よろしくお願いします。 VBAに関する質問です。 ワークシートのタブに「12月 1日」とか「 2月28日」とか「 6月14日」などの名前が付けられています。これらのワークシートを,4月1日から翌年の3月31日までの順に並べ替えるプログラムを作りたいのですが,どのようにしたらよいか教えてください。 全てのワークシートの名前を取得し,”月”が何文字目に入っているかを検索し,Left関数で月数を切取り,それによって年度を加え,これをCDateで日付関数に変換したりなどして見ました。 For Each Wsht In Worksheets If InStr(Wsht.Name, "月") = 3 Then Tuki = CInt(Trim(Left(Wsht.Name, 2))) If Tuki > 0 And Tuki < 4 Then Hiduke = "2012年" & Wsht.Name ElseIf Tuki > 3 And Tuki < 10 Then Hiduke = "2011年" & Wsht.Name End If ElseIf InStr(Wsht.Name, "月") = 4 Then Hiduke = "2011年" & Wsht.Name End If Next 日付関数への変換は抜いていますが,この後,Date型の配列と文字列型の配列を用意し, Date型の配列にはCDateで変換した値を代入し,文字列型の方には,元々のシートタブの値を代入し,Date型の方で,最小値ををfor~nextで探し出すなどして,文字列型の方を添え字の順になるように並び替えて・・・・もう手一杯です。 さらにこれをWorksheets(" 6月14日").move before:=**** などというメソッドを使って並び替えなくてはいけないとなると,もう私の力ではオーバーフローです。 すみません。どなたかお助けください。

質問者が選んだベストアンサー

  • ベストアンサー
  • MARU4812
  • ベストアンサー率43% (196/452)
回答No.2

ついでに > 日付関数への変換は抜いていますが, の話ですが、 > If InStr(Wsht.Name, "月") = 3 Then > ElseIf InStr(Wsht.Name, "月") = 4 Then なんで上記の条件がいるのか分からないです。 単純に月日を抜き出したいなら、もっと一般化 すればいいとおもいます。 Sub test()   Dim Wsht_Name As String   Wsht_Name = "12月 1日"   Debug.Print GetTuki(Wsht_Name)   Debug.Print GetHiduke(Wsht_Name)   Wsht_Name = " 13月  134日"   Debug.Print GetTuki(Wsht_Name)   Debug.Print GetHiduke(Wsht_Name)   Wsht_Name = "3月4日"   Debug.Print GetTuki(Wsht_Name)   Debug.Print GetHiduke(Wsht_Name)   Wsht_Name = "3 月4567  日"   Debug.Print GetTuki(Wsht_Name)   Debug.Print GetHiduke(Wsht_Name) End Sub Function GetTuki(Wsht_Name As String) As Integer   GetTuki = CInt(Left(Wsht_Name, InStr(Wsht_Name, "月") - 1)) End Function Function GetHiduke(Wsht_Name As String) As Integer   GetHiduke = CInt(Mid(Wsht_Name, InStr(Wsht_Name, "月") + 1, (InStr(Wsht_Name, "日") - 1) - InStr(Wsht_Name, "月"))) End Function

その他の回答 (4)

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.5

ソートを自作するのが面倒なので、1ワークシートを作業シートにしてそこでソートした。 ーー 下記で平成23年の部分は適当に修正必要。 年月が同年とみなす合 Sub test01() Dim d1(100), d2(100), d3(100) Worksheets("Shweet1").Columns("H:H").NumberFormatLocal = "@" '文字列に設定して日付と解釈されなくする i = 1 'Sheet1における書き出し最初行 For Each sh In Worksheets '全シート数 'MsgBox sh.Name If sh.Name <> "Sheet1" Then 'Sheet1(作業シート)以外を処理対象にする d1(i) = sh.Name d2(i) = DateValue("平成23年" & d1(i)) d3(i) = i Worksheets("Sheet1").Cells(i, "H") = d1(i) Worksheets("Sheet1").Cells(i, "I") = d2(i) Worksheets("Sheet1").Cells(i, "J") = d3(i) i = i + 1 End If Next sn = i - 1 'シート数 '---日付でソート(I列) With Worksheets("Sheet1") .Range("H1:J" & sn).Sort Key1:=Range("I1"), Order1:=xlAscending End With '---シート並べ替え。 For i = 1 To sn n = Worksheets("Sheet1").Cells(i, "H") 'シート名 Worksheets(n).Move before:=Worksheets(i) Next i End Sub ================== 1-3月を来年と解釈する場合。 Sub test02() Dim d1(100), d2(100), d3(100) Worksheets("Sheet1").Columns("H:H").NumberFormatLocal = "@" i = 1 For Each sh In Worksheets '全シート数 'MsgBox sh.Name If sh.Name <> "Sheet1" Then 'Sheet1(作業シート)以外を処理対象にする d1(i) = sh.Name d2(i) = DateValue("平成23年" & d1(i)) d3(i) = i If Month(d2(i)) >= 1 And Month(d2(i)) <= 3 Then '1-3月は次年と解す d2(i) = DateSerial(Year(d2(i)) + 1, Month(d2(i)), Day(d2(i))) End If Worksheets("Sheet1").Cells(i, "H") = d1(i) Worksheets("Sheet1").Cells(i, "I") = d2(i) Worksheets("Sheet1").Cells(i, "J") = d3(i) i = i + 1 End If Next sn = i - 1 'シート数 '---日付でソート(I列) With Worksheets("Sheet1") .Range("H1:J" & sn).Sort Key1:=Range("I1"), Order1:=xlAscending End With '---シート並べ替え。 For i = 1 To sn n = Worksheets("Sheet1").Cells(i, "H") 'シート名 Worksheets(n).Move before:=Worksheets(i) Next i End Sub

emikouji
質問者

お礼

imogasiさんありがとうございました。 参考にさせていただき,解決いたしました。 作成した,コードを,補足にのせておきましたので,ご覧ください。 本当にありがとうございました。

emikouji
質問者

補足

Sub Sort_Sheet() Dim Hi As String Dim Key As String Dim ShtName() As String Dim Soeji As Integer Dim i As Integer Dim Saidai As Variant Dim SaidaiSoeji As Integer Dim HidukeJun() As String Dim j As Integer Soeji = 1 ReDim ShtName(1 To 2, 1 To 1) For Each Wsht In Worksheets If Right(Wsht.Name, 1) = "日" Then If GetHiduke(Wsht.Name) < 10 Then Hi = "0" & CStr(GetHiduke(Wsht.Name)) Else Hi = CStr(GetHiduke(Wsht.Name)) End If If GetTuki(Wsht.Name) > 0 And GetTuki(Wsht.Name) < 4 Then Key = "10" & CStr(GetTuki(Wsht.Name)) & Hi ElseIf GetTuki(Wsht.Name) > 3 And GetTuki(Wsht.Name) < 10 Then Key = "0" & CStr(GetTuki(Wsht.Name)) & Hi ElseIf GetTuki(Wsht.Name) > 9 And GetTuki(Wsht.Name) < 13 Then Key = CStr(GetTuki(Wsht.Name)) & Hi End If ShtName(1, Soeji) = Key ShtName(2, Soeji) = Wsht.Name Soeji = Soeji + 1 ReDim Preserve ShtName(1 To 2, 1 To Soeji) End If Next ReDim Preserve ShtName(1 To 2, 1 To Soeji - 1) ReDim HidukeJun(UBound(ShtName, 2)) Saidai = CInt(ShtName(1, 1)) For j = 1 To Soeji - 1 For i = 1 To Soeji - 1 If CInt(ShtName(1, i)) > Saidai Then Saidai = CInt(ShtName(1, i)) SaidaiSoeji = i End If Next HidukeJun(j) = ShtName(2, SaidaiSoeji) ShtName(1, SaidaiSoeji) = "0" Saidai = 0 Next For i = 1 To Soeji - 1 If i = 1 Then Worksheets(HidukeJun(i)).Move before:=Worksheets("master") Else Worksheets(HidukeJun(i)).Move before:=Worksheets(HidukeJun(i - 1)) End If Next End Sub Function GetTuki(Wsht_Name As String) As Integer GetTuki = CInt(Left(Wsht_Name, InStr(Wsht_Name, "月") - 1)) End Function Function GetHiduke(Wsht_Name As String) As Integer GetHiduke = CInt(Mid(Wsht_Name, InStr(Wsht_Name, "月") + 1, (InStr(Wsht_Name, "日") - 1) - InStr(Wsht_Name, "月"))) End Function Function の GetTuki と GetHiduke はMARU4812さんのものをそのまま使わせていただきました。ありがとうございました。

  • mzon
  • ベストアンサー率48% (26/54)
回答No.4

すこしたのしそうだったのでつくってみました。 参考になれば幸いです。 ----------------------- ' 空シートにボタン作って、押された時に動作するようにしてみました。 ' 年が1999年になっているのはうるう年なので2月29日があるからです。 ' 当年でよい場合は1999の部分を当年2000の部分を翌年にしてみてください。 Private Sub CommandButton1_Click() On Error Resume Next ' シートがなくてもとまらないようにする Dim xlsSheet As Worksheet ' シートの存在確認用 Dim dSheetDay As Date ' 処理日付 Dim sSheet(0 To 1) As String ' シートの名前用 0:対象の日、1:前の日 dSheetDay = CDate("1999/04/01") ' 4月1日(初期値)2000年は2/29対応 sSheet(1) = "" ' 初期値空白(先頭へ移動) Do sSheet(0) = Format(dSheetDay, "M月D日") ' 日付をシートの名前に変換(1月1日)となる。 'sSheet(0) = StrConv(Format(dSheetDay, "M月D日"), vbWide) ' 漢字の場合はこっち(1月1日)となる ' シートの有無確認 Set xlsSheet = Worksheets(sSheet(0)) ' あればオブジェクトが入る If Not xlsSheet Is Nothing Then ' シートがある場合 If sSheet(1) <> "" Then ' 先頭以外の場合() ThisWorkbook.Sheets(sSheet(0)).Move after:=Sheets(sSheet(1)) ' 対象の日付を前回の後につける End If Set xlsSheet = Nothing ' オブジェクト開放(忘れるとメモリリークする) sSheet(1) = sSheet(0) ' 前の日を記憶(この後に次の日が並ぶ) End If dSheetDay = DateAdd("d", 1, dSheetDay) ' 1日移動 If CLng(Format(dSheetDay, "YYYYMM")) >= 200004 Then ' 次の年(2000年04)になったら Exit Do ' ループおしまい End If Loop End Sub

emikouji
質問者

お礼

mzonさんありがとうございました。 参考にさせていただき,解決いたしました。 作成した,コードを,回答(5)さんの補足にのせておきましたので,ご覧ください。 本当にありがとうございました。

  • mu2011
  • ベストアンサー率38% (1910/4994)
回答No.3

一案です。 別シートに4月2日から3月31日の文字列リストを作り、その行順に従って並び替える方法は如何でしょうか。 以下のコードを標準モジュールに貼り付けて実行してみて下さい。 Sub sample() On Error Resume Next '該当日付のシートがない場合の対応 Sheets("4月1日").Select Set st = sheets("別シート") For i = 1 To st.Cells(Rows.Count, 1).End(xlUp).Row Sheets(st.Cells(i, 1).Value).Move After:=ActiveSheet Next End Sub

emikouji
質問者

お礼

mu2011さんありがとうございました。 参考にさせていただき,解決いたしました。 作成した,コードを,回答(5)さんの補足にのせておきましたので,ご覧ください。 本当にありがとうございました。

  • MARU4812
  • ベストアンサー率43% (196/452)
回答No.1

日付に変換するのが難しいなら。。。 12月 1日 --> 1201 6月14日 --> 614(0614) 年度区切りなので1月から3月は 2月28日 --> 10228 の数値に変換したものをキーにして、並び替えれば 簡単なんじゃないかなぁ。 個別の配列を用意するより。。。 作業用シートを追加して、上記キーとシート名を 2列に並べておいて Range の Sort でセットで並び 替えてしまえば、あとは上から順番のシート順にして いくだけ?

emikouji
質問者

お礼

MARU4812さんありがとうございました。 参考にさせていただき,解決いたしました。 作成した,コードを,回答(5)さんの補足にのせておきましたので,ご覧ください。 本当にありがとうございました。

関連するQ&A

  • VBA Setステートメント

    エクセル2002使用です。 B列に本日の日付が入るようにワークシートに関数(DAY関数)が入っています。 そのB列を検索して、同じ日付け(数字)がなければ、今日の日付を入力するVBAを組もうと思っているのですが、 Setステートメントで実行時エラー13になります。 ご教示いただけませんでしょうか? Private Sub CommandButton1_Click() ' 出勤ボタン B列に同日日付があればキャンセル Dim tuki, Hiduke1 As String Dim Hiduke1kekka As Variant tuki = Range("B3").Value Hiduke1 = Range("D3").Value Worksheets(tuki & "月").Activate Set Hiduke1kekka = ActiveSheet.Columns("B:B") _ .Find(What:=Hiduke1, After:=ActiveCell, LookIn:=xl, LookAt _ :=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _ False, MatchByte:=False, SearchFormat:=False) If Hiduke1kekka Is Nothing Then ActiveSheet.Range("D1000").End(xlUp).Select Selection.Value = "出" Worksheets("sheet1").Activate Else Worksheets("sheet1").Activate Exit Sub End If End Sub

  • INPUT関数で入力した日付でワークシートとセルに値をいれる。

    こんにちは、最近VBAを勉強し始めたのですが、 躓いてしまいました。 すでにあるワークシートからINPUT関数で”20101016”を入力して ワークシートをコピー(シート名は”20101016”)する事はできたのですが このシートに”2010年 10月 16日 (曜日)”を表示する事ができないのです。 指定したセルには”20101016”が入っているのですが 表示が"###################”になってしまいます。 (”負の日付又は時間は###の表示になります。”の意味がわかりません。) 書式設定で日付等をいじっても変化がありません。 どなたか、ご教示願います。 Sub 新規シート() Dim tuki As String ActiveSheet.Copy after:=ActiveSheet   'アクティブシートの後ろへコピーを作る。 Range("a46:r57").Select   'コピー元の値を削除 Selection.ClearContents Range("a1").Select tuki = InputBox("日付を半角英数字で入力してください。" & Chr(13) & _ "yyyymmdd 形式で入れてね!", "日付入力")   'tukiに8桁を入力 If tuki = "" Then Application.DisplayAlerts = False ActiveSheet.Delete Application.DisplayAlerts = True   '入力が無い場合、作成したシートを削除 Else On Error Resume Next ActiveSheet.Name = tuki   '新規ワークシート名に”tuki”を代入 Range("d6").Value = tuki  ’ここが問題! If Err.Number = 1004 Then MsgBox "日付が重複しています。" Application.DisplayAlerts = False ActiveSheet.Delete Application.DisplayAlerts = True   'シート名が重複した場合、警告後に削除 End If End If End Sub

  • iアプリでint型、または文字列をDate型に変換する方法

    iアプリでint型、または文字列をDate型に変換する方法を教えてください。 int nen,tuki,hi; String DateStr; Date Hiduke; nen = 2002; tuki = 11; hi = 1; DateStr = Integer.toString(nen) + "-" + Integer.toString(tuki) + "-" + Integer.toString(hi); として、nen,tuki,hiから、またはDateStrからHidukeに変換したいのです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • エクセル マクロ 複数セルの色付けについて

    マクロ初心者で苦戦しており、教えていただけると大変ありがたいです。 エクセルの複数のシートに、問2_1 、問2_2 、問2_10 (全部で問は2_28まであります)等の文字列があり、その文字に合わせて、そのセルだけ色を付けたいと考えております。 今書いているコードだと、ワークシートのA列にある場合は色が付けられるのですが、それ以外に色が付けられません。どこが間違っているでしょうか? どうぞご指導お願いいたします。 Sub 色つけ() Dim Maxrow As Long Dim i As Long Maxrow = Cells(Rows.Count, i).End(xlUp).Row For i = 1 To Maxrow If InStr(Cells(i, 1), "2_1 ") > 0 Then Cells(i, 1).Interior.ColorIndex = 6 If InStr(Cells(i, 1), "2_2 ") > 0 Then Cells(i, 1).Interior.ColorIndex = 6 If InStr(Cells(i, 1), "2_23 ") > 0 Then Cells(i, 1).Interior.ColorIndex = 23 If InStr(Cells(i, 1), "2_13 ") > 0 Then Cells(i, 1).Interior.ColorIndex = 4 If InStr(Cells(i, 1), "2_6 ") > 0 Then Cells(i, 1).Interior.ColorIndex = 7 Next i End Sub

  • エクセルマクロの改良

    テキストボックス内に×の文字列があれば、エンターキーを押すたびに×の前にカーソルが行きます。 最後の×の後ろにもカーソルが行くようにしたいのですがご教授くださいませ。 If .Value Like "*×*×*" Then s = .SelStart ss = InStr(s + 2, .Value, "×") If ss >= s + 2 Then .SelStart = ss - 1 KeyCode = 0 End If ElseIf .Value Like "*×*×*×*×" Then s = .SelStart ss = InStr(s + 2, .Value, "×") If ss >= s + 2 Then .SelStart = ss - 1 KeyCode = 0 End If

  • 関数 各条件により貼り付けるデータを変えたい

    二つのワークシートがあり、各条件により貼り付けるデータを変えたいのですが、IF文等の関数で可能でしょうか。 ワークシートW   A列    B列    C列    D列    E列   G列 1 倉庫   商品1   10円 2       商品2   50円 3 倉庫   商品3   20円 4       商品4   15円 5              17円 ワークシートY   A列     B列    C列 1 if関数(1)  if関数(2)  if関数(3) 2 if関数(4)  if関数(5)  - このデータで、以下のことをしたいのですが、可能でしょうか ワークシートWのA1とB1に文字がある場合、ワークシートYのA1をワークシートWのD1に貼り付ける ※これを同じ条件で、貼り付けるデータを「ワークシートWのE1にワークシートB1を貼り付け」、 「ワークシートWのG1にワークシートWのC1を貼り付け」をしたい また、ワークシートWのA1に文字がないが、B列に文字がある場合、ワークシートY2をワークシートWのD2に貼り付ける ※これを同じ条件で、貼り付けるデータを「ワークシートWのE2=ワークシートYのB2」、 「ワークシートWのG2にワークシートWのC2を貼り付け」をしたい なお、ワークシートYにはIF文が入力されています。 ご存知の方いらっしゃればお願いします。

  • 空白セルの記述方法

    Excel VBAで日付データがA列、通貨データがB列にあるとして シート1のセル(A:1)、セル(B:2)が空白セルとして条件式を作りたいのですが記述方法はどのようになりますか? 下記でよろしいでしょうか? If CDate(sheet1.cell(A:1).value) = Empty then If CCur(sheet1.cell(B:1).value) = Empty then

  • エクセル2000マクロデバッグエラー

    下記のマクロを書いていますがエクセル95では多分うまくいったのですが 2000で動かすとエラーになります。 tuki = Sheets("mmm").Cells(5, 12).Text→ここでインデックスが有効範囲にありません 5行目の12列目には、200201データが入っています。書式は###です。 原因を教えてください。 なにをしているか記述の意味がわかれば教えてください。 Dim i, C_COUNT, folda, work, t folda = "C:\test\" tuki = Sheets("mmm").Cells(5, 12).Text tuki = Val(Right(tuki, 2)) If tuki = 12 Then tuki = 1 Else tuki = tuki + 1 End If tuki = Format(Str(tuki), "00") Workbooks.Add F_NAME = "Kei" + tuki + "tuki.XLS" ActiveWorkbook.SaveAs Filename:=folda + F_NAME, _ FileFormat:=xlNormal, Password:="", WriteResPassword:="", _ ReadOnlyRecommended:=False, CreateBackup:=False

  • VBAでelseに対応するifがありませんとエラー

    VBA初心者です 入力した数値(0から5)により、呼んでくる列を変えたいマクロを組んでいます if then elseif end ifで条件式を作ったのですが、 「elseに対応するifがありません」とエラーが出て進みません elseifが悪いのかと思い、条件を1つに絞ると上手く動きます(この際はendifは不要) ネット検索や参考書を見てますが、分かりません どなたか間違いを指摘して頂けませんか? Sub inputboxA() Dim nDat As String nDat = inputbox("何ヶ月目ですか?") If IsNumeric(nDat) = False Then MsgBox ("0から5までの値を入力して下さい") Exit Sub End If If nDat = 0 Then mm = 16 '0なら16列からデータを呼んでくる ElseIf nDat = 1 Then mm = 20 'ここでエラーが出る  1なら20列目からデータを呼んでくる ElseIf nDat = 2 Then mm = 24 '2なら24列目からデータを呼んでくる ElseIf nDat = 3 Then mm = 28 '3なら28列目からデータを呼んでくる ElseIf nDat = 4 Then mm = 32 '4なら32列目からデータを呼んでくる ElseIf nDat = 5 Then mm = 36 '5なら36列目からデータを呼んでくる End If 'データを呼んでくる For r = 4 To 2000 '処理するSheet1の行数範囲 b = Sheets(1).Cells(r, 1) 'bにA列の値を代入 For t = 6 To 2000 '検索するSheet3の行数範囲 If Sheets(3).Cells(t, 7) = b Then 'Sheet1のA列の値とSheet3のA列が一致した場合 y = Sheets(3).Cells(t, mm) 'yにB列の値を代入 Sheets(1).Cells(r, 6).Value = y 'Sheet1のB列に値を入力 Exit For '値が見つかったのでForを終了 End If Next Next End Sub

  • ワークシートの削除

    For SheetSakujo = 3 To SheetCount - 1 Worksheets(SheetSakujo).Select If ActiveSheet.Name <> "★" Then If Range("A2") = "" Then ActiveWindow.SelectedSheets.Delete End If ElseIf ActiveSheet.Name = "★" Then Exit For End If Next VBAでワークシートの削除を行っています。 A2が空白のシートを消そうと思って上記のようなコードをくみましたが、 削除されるとシートが減ってしまうため、次のシートも空白だった場合、消されないで飛ばされてしまいます。 3枚目のシート:空白 4枚目のシート:空白 5枚目のシート:空白     ↓ sheetsakujoが「3」なので3枚目は削除される。 次の4枚目のシートが3枚目が削除されたため、「3番目のシート」になるため、次に削除されるのは5枚目のシート。 この場合、どのようにしたらいいのでしょうか?

専門家に質問してみよう