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

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

ただいまの
回答率

87.80%

【VBA】入れ子のFor文が期待通りの処理をしない

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 462

score 18

VBAのネストしているFor文が期待通りに実行されません。

以下に現状をまとめました。

【作業環境】
Windows 7 Professional
Excel 2007

【やりたいこと】
テンプレートシート(オブジェクト名:wsTemplate2)
→E2セルから右に開始日~終了日までを表示

【困っていること】
テンプレートシートのE2セルから右に開始日~終了日までが表示されない。

現状は以下の通り。

①E2~AD2まで「1900/1/31」が入る

②本来なら日付はE2~AI2まで入る。データの個数が4つ足りない

【参照データ】
カレンダーシート(オブジェクト名:wsDateList)
→D2セル「2021/01/01」(開始日)
→E2セル「2021/01/31」(終了日)

【試したこと】
・For文を入れ子にぜずにそれぞれの処理をイミディエイトで確認したところ、
期待通りの処理になった
→入れ子にすると期待通りの処理にならない

イミディエイトで動きを確認したところ、
入れ子になっているFor文のどちらも正しく機能していません。
日付は2021/01/28から始まっており、
21個ずつ同じものが表示されています。
列の移動も9(I列)から始まっていますが、
テンプレートシートには5(E列)から表示されています。

VBAの勉強中であるため分かりにくい箇所があるかもしれませんが、
どうぞよろしくお願いいたします。

Public Sub template()


    Dim dateStartDate As Date   '開始日
    Dim dateEndDate  As Date    '終了日
    Dim loncntDay As Long       '開始日~終了日の日数カウント用変数
    Dim Dayone As Date          '日付用変数
    Dim cntColl As Long         '列変数


    dateStartDate = wsDateList.Range("D2")                 '「開始日」
    dateEndDate = wsDateList.Range("E2")                   '「終了日」
    loncntDay = DateDiff("d", dateStartDate, dateEndDate)  '「開始日」~「終了日」を日単位で数える

    For Dayone = 0 To loncntDay  '開始日から1日単位で増えていく(※開始日も表示したいので0からスタート)
        For cntColl = 5 To loncntDay  '列移動

            wsTemplate2.Cells(2, cntColl).Value = DateAdd("d", 1, Dayone) '1~開始日-終了日の日数
            Debug.Print DateAdd("d", Dayone, dateStartDate)
            Debug.Print "2, "; cntColl

        Next cntColl
    Next Dayone

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+1

2重ループの必要性はまったくありません。
またDate型は整数値が日を表しているので、単純に開始日にループの値を加算していけばよいです。
という感じで以下のように修正しました。

    dateStartDate = wsDateList.Range("D2")                 '「開始日」
    dateEndDate = wsDateList.Range("E2")                   '「終了日」
    loncntDay = DateDiff("d", dateStartDate, dateEndDate)  '「開始日」~「終了日」を日単位で数える
    cntColl = 5
    For Dayone = 0 To loncntDay  '開始日から1日単位で増えていく(※開始日も表示したいので0からスタート)
        wsTemplate2.Cells(2, cntColl).Value = dateStartDate + Dayone
        cntColl = cntColl + 1
    Next Dayone

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/30 13:59

    >2重ループの必要性はまったくありません。
    指摘をされてようやく気付くことができました。
    エクセルで1日単位で加算する場合、
    以下の処理になるのだから当然ですね。

    A1 B2 C2
    1/1 A1+1 B2+1


    正しいコードだけでなく、
    ご説明までしていただき深く感謝しております。
    またひとつVBAの理解が深まりました。

    キャンセル

+1

解決済みですが、こんな方法も。

Public Sub template()

    Dim dateStartDate As Date   '開始日
    Dim dateEndDate  As Date    '終了日
    dateStartDate = wsDateList.Range("D2").Value
    dateEndDate = wsDateList.Range("E2").Value

    Dim DateCell As Range
    Set DateCell = wsTemplate2.Range("E2") '日付入力セル

    Dim Dayone As Date 
    For Dayone = dateStartDate To dateEndDate '開始日から終了日までループ
        DateCell.Value = Dayone
        Set DateCell = DateCell.Offset(, 1) ’入力セルを右へ移動
    Next Dayone

End Sub

Date型も中身は数値型(倍精度浮動小数点型)なのでForでループできます。


ループを使わずにやる方法も。

Public Sub template1()

    Dim dateStartDate As Date   '開始日
    Dim dateEndDate  As Date    '終了日
    Dim loncntDay As Long

    dateStartDate = wsDateList.Range("D2")
    dateEndDate = wsDateList.Range("E2")
    loncntDay = DateDiff("d", dateStartDate, dateEndDate)

    wsTemplate2.Range("E2").Value = dateStartDate
    With wsTemplate2.Range("F2").Resize(, loncntDay)
        .Formula = "=E2+1" '左のセルに+1
        .Value = .Value    '式を値に変換
    End With

End Sub

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/30 14:26

    解決済みにもかかわらず回答をしてくださりありがとうございます。
    Date型も数値なのですね。知らなかったので勉強が足りていませんでした。
    VBA初心者の私でも理解できるコードですごく見やすいです。
    こんなコードが書けるようよう今後も頑張っていきます。

    キャンセル

checkベストアンサー

0

こんな考え方も。

Public Sub template()

    Dim dateStartDate As Date   '開始日
    Dim dateEndDate  As Date    '終了日
        dateStartDate = wsDateList.Range("D2").Value                 '「開始日」
        dateEndDate = wsDateList.Range("E2").Value                   '「終了日」

    Dim cntColl As Long         '列変数
        cntColl = 5

    Do While wsTemplate2.Cells(2, cntColl - 1).Value <> dateEndDate '終了日でない間続ける
        wsTemplate2.Cells(2, cntColl).Value = dateStartDate + cntColl - 5
        cntColl = cntColl + 1
    Loop

End Sub

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/30 13:50

    Do Whileを使用しての処理は考え付きませんでした。
    さらにテンプレートシートに表示される日付がきちんと2021/1/1~2021/1/31になっていて嬉しいです。
    2021がどうして1900になるのか調べても上手く理解できなかったためとても助かりました。
    ①と②を解決していただいたradames1000さんの回答をベストアンサーとさせていただきます。

    キャンセル

0

'    dateStartDate = wsDateList.Range("D2")                 '「開始日」
'    dateEndDate = wsDateList.Range("E2")                   '「終了日」
    dateStartDate = wsDateList.Range("D2").value                 '「開始日」
    dateEndDate = wsDateList.Range("E2").value                   '「終了日」

コード

Loopはどちらかにしましょう

    cntColl = 5
    For Dayone = 0 To loncntDay  '開始日から1日単位で増えていく(※開始日も表示したいので0からスタート)

            wsTemplate2.Cells(2, cntColl + Dayone).Value = DateAdd("d", 1, Dayone) '1~開始日-終了日の日数
            Debug.Print DateAdd("d", Dayone, dateStartDate)
            Debug.Print "2, "; cntColl

    Next Dayone

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/30 13:39

    ループを1つに絞っての処理の方法が思いつかなかったのでとても勉強になります。
    ありがとうございます!

    キャンセル

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

  • ただいまの回答率 87.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る