ダウンロードとコピペで使えるExcelVBAのカレンダーコントロール

ダウンロードとコピペで使えるExcelVBAのカレンダーコントロール

セルをダブルクリックしたらカレンダーコントロールが開いて、日付をクリックすると最初のセルに入力される、というマクロです。難しいところはわからなくてもいいから、かんたんシンプルにサクッと使える方向性を目指しました。


はじめに

当ブログでは2014年に「イチから自作」コンセプトでExcelのカレンダーコントロールを作りましたが(当時の記事)、その後、書籍へ掲載したり改良を重ねて、ここで紹介しているのはバージョンアップしているものです。

なお、がんばってマクロでやるより、きぬあささんのアドインも超便利です! こちらもぜひどうぞ!

動画版もあります

今回の記事は動画でも解説してます。テキストよりそっちのほうが好きという方はこちらからどうぞ!

ダウンロード

こちらからzipファイルをダウンロードして、展開してください。環境の制限によってダウンロードできない方は、こちらを参考に自作することも可能です。

DLの前にお読みください

Windows10/11、Microsoft365のExcelで動作確認を行っています。ご利用の際はOfficeを最新バージョンへアップデートしてください。OSやOfficeのバージョンが古い場合、一部動作しない可能性があります。

また、コードには細心の注意を払っておりますが、無保証のコントロールとさせていただいています。いかなる理由により損害等が発生しても一切責任を負いかねますので、あらかじめご了承のうえご利用ください。

更新履歴

  • ターゲットが結合セルだった場合の日付を読めないバグに対応(2022/11/4)
  • ダブルクリックしたセルの近くにカレンダーが表示されるように改良(2022/11/14)
  • カレンダーの表示位置をデフォルト(画面中央)へ戻しました(2022/12/5)

※変更により、動画で映っている画面と異なる部分があります。

以下の3つのファイルが入っています。

  • F_CalenderForm.frm
  • F_CalenderForm.frx
  • M_CalendarSetting.bas

インポート

VBEのプロジェクトエクスプローラー内の「VBAProject」を右クリックして「ファイルのインポート」を選択し、「F_Calendar.frm」と「M_CalendarSetting.bas」をそれぞれ読み込みます。

プロジェクトエクスプローラーがこのようになっていれば、フォームモジュール「F_Calendar」と標準モジュール「M_CalendarSetting」が正しく読み込まれています。

シートモジュールを開く

「カレンダー」フォームを利用したいシートモジュールを選びます。ダブルクリックで開きます。

シートモジュールにコピペするコード

該当のシートモジュールに以下をコピペします。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  Call setCalendarDateForCell(Target)
End Sub

これで、コードを書いたシートのいずれかのセルをダブルクリックすると「カレンダー」フォームが起動し、クリックした日付が対象セルに挿入されます。右上のスピンボタンで、左側が-1月、右側が+1月へ遷移します。

(2024/3/20追記)デフォルトでは、カレンダーから日付が挿入された直後は、セルが「編集モード(セルの中にカーソルが入っている状態)」になります。これは、セルをダブルクリックした操作によるものです。以下の1文を入れると、編集モードを回避できます。お好みでどうぞ。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  Cancel = True
  Call setCalendarDateForCell(Target)
End Sub

カレンダー起動の範囲を指定するときは、Call setCalendarDateForCell直前の行にCancel = Trueを入れてください。

カスタマイズ

特定のセルだけ

そのままだと全セル動いてしまうので、特定のセルだけカレンダーを起動したい場合は、以下のコードに差し替えます。「”$A$1″」の部分を好きなセルに書き換えてください。「”」と「$」は必要です。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Target.Address <> "$A$1" Then Exit Sub 'A1セル以外なら終了
  Call setCalendarDateForCell(Target)
End Sub

結合セルは以下の形で書きます。「”$A$1:$B$2″」部分はすべて大文字・半角英数字です。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Target.Address <> "$A$1:$B$2" Then Exit Sub 'A1:B2の結合セル以外なら終了
  Call setCalendarDateForCell(Target)
End Sub

(2023/7/15追記)コメント欄で教えていただきました! 結合セルで上のコードでうまくいかない場合、こちらでも試してみてください。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Intersect(Target, Range("A1:B2")) Is Nothing Then Exit Sub 'A1:B2の結合セル以外なら終了
  Call setCalendarDateForCell(Target)
End Sub

特定セルを複数にする

カレンダーを起動したいセルを複数セルで指定したい場合は、以下のコードに差し替えます。好きなセルに書き換えてください。増やす場合は「,」で区切ります。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Intersect(Target, Range("A1, B2, C3")) Is Nothing Then Exit Sub '指定セル以外なら終了
  Call setCalendarDateForCell(Target)
End Sub

以下のようにセルは単一でも範囲でも大丈夫です。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Intersect(Target, Range("A1, B2:C3, D4:E5")) Is Nothing Then Exit Sub '指定セル以外なら終了
  Call setCalendarDateForCell(Target)
End Sub

特定の列/行だけ

特定の列だけカレンダーを起動したい場合は、以下のように書きます。A列なら1、B列なら2、という具合に数値で指定します。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Target.Column <> 4 Then Exit Sub '4列目(D列)以外なら終了
  Call setCalendarDateForCell(Target)
End Sub

特定の行だけカレンダーを起動したい場合は、以下のように書きます。数値で指定します。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Target.Row <> 2 Then Exit Sub '2行目以外なら終了
  Call setCalendarDateForCell(Target)
End Sub

A~C列のとき、のように書く場合は以下です。行にする場合はTarget.ColumnTarget.Rowに変更してください。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If 1 <= Target.Column And Target.Column <= 3 Then 'A~C列のとき
    Call setCalendarDateForCell(Target)
  End If
End Sub

AまたはCまたはE列のとき、のように書く場合は以下です。行にする場合はTarget.ColumnTarget.Rowに変更してください。

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
  If Target.Column = 1 Or Target.Column = 3 Or Target.Column = 5 Then 'AまたはCまたはE列のとき
    Call setCalendarDateForCell(Target)
  End If
End Sub

表示できる年数を変更する

カレンダー上の年数を変更したい場合は、VBEでF_Calendarを右クリックして、「コードの表示」を選択します。

「UserForm_Initialize」プロシージャの、図でハイライトしてある -3 To 3 の部分をお好きな数値に変更してください。±5年とかにしてもいいですし、前後で違う数でも大丈夫です。

For i = 0 To 5 にすると、以下のような表示になります。

以上です! 選択肢の1つとして、こんな方法もあるんだ~と思っていただけたら嬉しいです。

追記1: 祝日対応

リクエストをいただいたので作ってみました。こちらのwebAPI(Holidays JP API (日本の祝日API))をお借りしており、永続的ではないこと、トラブルなどに対して無保証であることをご了承ください。

こちらのカスタマイズではインターネット環境が必須です。年を切り替える際にその年の祝日を取得するため、PCスペックやネット回線速度などによって読み込みに時間がかかる場合があります。ご自身の環境にて実用に耐えうるかご判断ください。

以下、実装方法です。最新版をDLしてインポートしてからはじめてください。

フォームモジュール「F_Calendar」を右クリックして、「コードの表示」を選択してください。一番上のOption Explicitの次に以下のハイライト部分を追加してください。

'# 「カレンダー」フォーム
Option Explicit
Private holidayList As String '祝日リスト格納用

続いて、同じ「F_Calendar」モジュール内の「cmb_year_Change」プロシージャへ、ハイライト部分を追加してください。

Private Sub cmb_year_Change()
  '## 年が変更された時
  
  'その年の祝日の取得 Holidays JP API (日本の祝日API) https://holidays-jp.github.io/ をお借りしています
  Dim httpReq As Object
  Set httpReq = CreateObject("MSXML2.XMLHTTP") 'HTTPリクエスト用オブジェクト作成
  httpReq.Open "GET", "https://holidays-jp.github.io/api/v1/" & Me.cmb_year.Value & "/date.json"
  httpReq.send '送信
  Do While httpReq.readyState < 4 '待機
    DoEvents
  Loop
  holidayList = httpReq.ResponseText
  Set httpReq = Nothing
  
  Call setCalendar
End Sub

続いて、同じ「F_Calendar」モジュール内の「setCalendar」プロシージャへ、ハイライト部分を追加してください。

Private Sub setCalendar()
  '## カレンダーの作成と表示
  '略
    
  For i = 1 To 37 'ラベルの初期化
    With Me("lbl_day" & i)
      .Caption = "" 'キャプション
      .BorderStyle = fmBorderStyleNone '枠なし
      .BackColor = Me.BackColor 'フォームと同じ背景色へ
      Select Case i Mod 7
        Case 1
          .ForeColor = vbRed '日曜は文字色を赤
        Case 0
          .ForeColor = vbBlue '土曜は文字色を青
        Case Else
          .ForeColor = vbBlack 'その他(平日)は文字色を黒
      End Select
    End With
  Next
  
  '略
  
  Dim tgtDay As Date '日付生成用変数
  For i = 1 To endDay '1日から月末日まで
    tgtDay = yy & "/" & mm & "/" & i '該当日付生成
    With Me("lbl_day" & n + i) '該当のラベルに対して
      .Caption = i '日を入れる
      If tgtDay = Date Then '今日なら
        .BorderStyle = fmBorderStyleSingle '枠を付ける
      End If
      If tgtDay = g_cldCurrentDate Then 'TextBoxの日と同じなら
        .BackColor = RGB(200, 200, 200) '背景色を付ける
      End If
      If InStr(holidayList, Format(tgtDay, "yyyy-mm-dd")) <> 0 Then '祝日リストに含まれていたら
        .ForeColor = vbRed '文字色を赤
      End If
    End With
  Next i
End Sub

以上で祝日が赤くなります。

追記2: ユーザーフォームのテキストボックスで使う

リクエストをいただきましたので、ユーザーフォームへのカスタマイズ方法を紹介した動画を作りました。

テキストボックス用にコピペするコード

標準モジュール「M_CalendarSetting」をダブルクリックして開き、一番下の空いている部分に下記をコピペします。

Public Sub setCalendarDateForTextBox(ByVal tgtTxb As MSForms.TextBox)
  '## カレンダーで選択した日付をテキストボックスに入力する

  If IsDate(tgtTxb.Value) = False Then '日付が入ってなければ
    g_cldCurrentDate = Date '今日の日付を格納
  Else
    g_cldCurrentDate = tgtTxb.Value 'テキストボックスの日付を格納
  End If

  F_Calendar.Show 'カレンダーを開く

  If g_isCldCancel = True Then Exit Sub 'キャンセル(バツボタンで閉じられた)なら終了
  tgtTxb.Value = g_cldPickedDate 'クリックされた日付を上書き
End Sub

その後、任意のユーザーフォーム上に作成したコマンドボタンのクリックイベントから、上に書いたプロシージャをCall setCalendarDateForTextBox(引数)のように呼び出します。引数にはカレンダーの日付を入力したいテキストボックスを設定してください。動画のほうで詳しく説明しています。

追記3: 年を和暦にする

カレンダーの「〇〇」年の部分を、「2023」→「令和5」のような和暦表示にするカスタマイズです。「F_Calendar」モジュール内のコードです。

「UserForm_Initialize」プロシージャの以下のハイライト部分を書き換えます。

Private Sub UserForm_Initialize()
  '## フォーム読込時
  
  Dim i As Long '汎用変数
  g_isCldCancel = False 'キャンセルフラグをFalseにしておく
  
  For i = -3 To 3 '前後3年分の年をリストに追加
    Me.cmb_year.AddItem Format(DateAdd("yyyy", i, g_cldCurrentDate), "ggge")
  Next i
  For i = 1 To 12 '月をリストに追加
    Me.cmb_month.AddItem i
  Next i
    
  Me.cmb_year.Value = Format(g_cldCurrentDate, "ggge") '年を指定
  Me.cmb_month.Value = Month(g_cldCurrentDate) '月を指定
End Sub

「setCalendar」プロシージャの以下のハイライト部分を書き換えます。

Private Sub setCalendar()
  '## カレンダーの作成と表示
  
  Dim i As Long '汎用変数
   
  If Me.cmb_year.Value = "" Or Me.cmb_month.Value = "" Then Exit Sub '年か月どちらか入ってなければ中止
  
  Dim yy As String '年取得
  yy = Me.cmb_year.Value
  Dim mm As Long '月取得
  mm = Me.cmb_month.Value
    
  '略
  
  Dim n As Long '月はじめの位置用変数
  n = Weekday(yy & "年" & mm & "月" & "1日") - 1 'その月の1日の曜日番号に、-1したもの
  
  Dim endDay As Long '月末日用変数
  endDay = Day(DateAdd("d", -1, DateAdd("m", 1, yy & "年" & mm & "月" & "1日"))) '算出
  
  '略
End Sub

「spn_monthUpDown_SpinUp」プロシージャの以下のハイライト部分を書き換えます。

Private Sub spn_monthUpDown_SpinUp()
  '## スピンボタンのアップクリック時
  
  On Error GoTo ErrHandler 'エラー時に「ErrHandler」行へジャンプする宣言
  
  If Me.cmb_month.Value = 12 Then '12月だったら
    Me.cmb_year.Value = Format(DateAdd("yyyy", 1, Me.cmb_year.Value & "/1/1"), "ggge") '年を+1
    Me.cmb_month.Value = 1 '1月へ
  Else
    Me.cmb_month.Value = Me.cmb_month.Value + 1 '月を+1
  End If
  
  '略
End Sub

「spn_monthUpDown_SpinDown」プロシージャの以下のハイライト部分を書き換えます。

Private Sub spn_monthUpDown_SpinUp()
  '## スピンボタンのダウンクリック時
  
  On Error GoTo ErrHandler 'エラー時に「ErrHandler」行へジャンプする宣言
  
  If Me.cmb_month.Value = 1 Then '1月だったら
    Me.cmb_year.Value = Format(DateAdd("yyyy", -1, Me.cmb_year.Value & "/1/1"), "ggge") '年を-1
    Me.cmb_month.Value = 12 '12月へ
  Else
    Me.cmb_month.Value = Me.cmb_month.Value - 1 '月を-1
  End If
  
  '略
End Sub

「putTgtDate」プロシージャの以下のハイライト部分を書き換えます。

Private Sub putTgtDate(ByVal i As Long)
  '## グローバル変数に取得した日付をセットする
  
  If Me("lbl_day" & i).Caption = "" Then Exit Sub 'ラベルが空だったら中止
  g_cldPickedDate = Me.cmb_year.Value & "年" & Me.cmb_month.Value & "月" & Me("lbl_day" & i).Caption & "日" '日付を生成して変数に格納
  Unload Me 'カレンダーを閉じる
End Sub

追記1の祝日対応をしている場合は、「cmb_year_Change」プロシージャの以下のハイライト部分を書き換えます。

Private Sub cmb_year_Change()
  '## 年が変更された時
  
  'その年の祝日の取得 Holidays JP API (日本の祝日API) https://holidays-jp.github.io/ をお借りしています
  Dim httpReq As Object
  Set httpReq = CreateObject("MSXML2.XMLHTTP") 'HTTPリクエスト用オブジェクト作成
  httpReq.Open "GET", "https://holidays-jp.github.io/api/v1/" & Year(Me.cmb_year.Value & "/1/1") & "/date.json"
  httpReq.send '送信
  Do While httpReq.readyState < 4 '待機
    DoEvents
  Loop
  holidayList = httpReq.ResponseText
  Set httpReq = Nothing
  
  Call setCalendar
End Sub

以上でカレンダーの表示は和暦になりますが、セルの表示は別です。該当のセルに対して「セルの書式設定」で「分類」を「日付」、「カレンダーの種類」を「和暦」にするなど、お好みのものへ変更してください。

追記4: イベントを一括制御する

リクエストをいただいたので別記事で書きました。このカレンダーの日付部分、37個のラベルのイベントプロシージャをクラスモジュールを使って省コード化する方法です。

公開日:2022/10/23
更新日:2024/03/20

87件のコメント

  1. 匿名 より:

    カレンダー起動時の日付を今日ではなく、excelの表の中で一番最後の日を基準にするにはどうしたら良いですか?

    • *yuko より:

      コメントありがとうございます。表を指定のセル範囲と仮定して、セル範囲内の日付で一番大きいものを起動時の初期値にする方法を考えてみました。

      インポートした標準モジュール「M_CalendarSetting」内の「setCalendarDateForCell」プロシージャへハイライト部分を追加し、8行目のセル範囲を任意のものに変更してみてください。

      Public Sub setCalendarDateForCell(ByVal tgtRange As Range)
        '## カレンダーで選択した日付をセルに入力する
      
        If IsDate(tgtRange.Cells(1, 1).Value) = False Then '日付が入ってなければ
          g_cldCurrentDate = Date '今日の日付を格納
          
          Dim maxDate As Date, rng As Range
          For Each rng In Range("A1:E5") 'セル範囲を指定する
            If IsDate(rng.Value) Then
              If maxDate = 0 Then
                maxDate = rng.Value
              Else
                If maxDate < rng.Value Then maxDate = rng.Value
              End If
            End If
          Next
          If maxDate <> 0 Then g_cldCurrentDate = maxDate
        Else
          g_cldCurrentDate = tgtRange.Cells(1, 1).Value 'セルの日付を格納
        End If
      
        F_Calendar.Show 'カレンダーを開く
      
        If g_isCldCancel = True Then Exit Sub 'キャンセル(バツボタンで閉じられた)なら終了
        tgtRange.Value = g_cldPickedDate 'クリックされた日付を上書き
      End Sub
      
  2. 匿名 より:

    失礼します。ありがたく使用させていただこうとしている者なのですが、
    結合したセルをターゲットにしたい場合はどうすればいいですか?

    • *yuko より:

      コメントありがとうございます。結合セルで試したところ、入力済みの日付を認識できない問題がありましたので、修正して更新いたしました。再度ダウンロードしてお試しください。自分では結合セルで使ったことがなかったので思わぬバグを発見させていただき、ありがとうございました。

  3. 匿名 より:

    調べて調べて調べまくってこちらに辿り着くことができました。

    とても素晴らしいものを与えてくださりありがとうございます。

    以下対応方法などお分かりでしたら教えてもらうことはできますか?
    ・祝日の反映は可能なのか。
    ・テーブル機能に使おうとしていて、最初のセルには反映できるのですが、追加行のセルへの対応がわかりません。

    • *yuko より:

      コメント&暖かいお言葉を、ありがとうございます。

      祝日対応ですが、外部APIを利用すれば不可能ではなさそうです。私も興味があるので作ってみようかと思いますので、少々お時間をください。ただ、外部サービスを利用するので永続的ではないこと、トラブルなどに対して無保証であることをご了承ください。

      > テーブル機能に使おうとしていて、最初のセルには反映できるのですが、追加行のセルへの対応がわかりません

      こちらの件は、テーブルに対して行列の挿入を行って試してみたのですが、現象の再現ができませんでした。再現できないことには対処ができず、申し訳ありません。

  4. 匿名 より:

    お返事ありがとうございます。
    需要がありそうな際のご対応で大丈夫ですので、何卒ご無理なさらずにお願い致します。

    最後に一つ、紹介されている列指定について複数の列はどのように指定したらいいのでしょうか?
    例えば、A列、C列、E列に指定したいなどの時です。もしくはA列~C列に指定などの時です。

    お忙しいところ恐縮ですが是非ご回答頂ければ幸いです。

    • *yuko より:

      祝日対応、本文に追記しましたので見てみてくださいね。

      列指定は、例では1つの条件を扱ったので、「If Target.Column <> ○ Then Exit Sub(○以外なら終了)」という書き方をしていますが、複数条件だと以下のような書き方のほうがわかりやすいかと思います。

      Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        If 1 <= Target.Column And Target.Column <= 3 Then 'A~C列のとき
          Call setCalendarDateForCell(Target)
        End If
      End Sub
      
      Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        If Target.Column = 1 Or Target.Column = 3 Or Target.Column = 5 Then 'AまたはCまたはE列のとき
          Call setCalendarDateForCell(Target)
        End If
      End Sub
      
  5. 匿名 より:

    お返事が遅くなってしまってすみません。
    2点とも対応してくださりありがとうございます。
    とても参考になり、助かります!

  6. 匿名 より:

    ターゲットのセルが結合セルだった場合に対応(2022/11/4)となっておりますが、結合セルで反応しません。
    対処方法を教えてください。

    • *yuko より:

      コメントありがとうございます。Windows10/11、Microsoft365のExcelで動作することを確認しております。OSやOfficeのバージョンが古い場合、一部動作しない可能性があります。Microsoft365をお使いの場合、Officeを最新バージョンへアップデートしてください。また、新規ブック状態から試して、拡張子は.xlsではなく.xlsmで動くかどうかお試しください。(既存ブックだと先に組み込まれている環境が動作に影響する場合があります。)

  7. 匿名 より:

    ダブルクリックした際のコントロールの表示位置が、だんだん下がってしまい30行以降になるとフレームアウトしてしまします。

    コントロール表示がフレームアウトすると、EXCELがフリーズしてしまいます。
    コントロール表示位置の調整は可能でしょうか??

    • *yuko より:

      コメントありがとうございます。2022/11/14の更新でダブルクリックしたセルの近くに表示されるようにしたのですが、画面やウィンドウの大きさによって動作が不安定であることがわかりました。デフォルト位置(画面中央表示)へ戻しましたので、お手数ですが最新版をDLし直してお試しください。

  8. 匿名 より:

    当方トリプルモニターで作業しているのですが、複数のセルに指定していまして、ダブルクリックした時にカレンダーの表示がすごい離れたところに表示されてしまいます。入力セルが横にずれればずれる程、隣の画面にカレンダーが現れ、更に隣の画面へと遠くなっていき、隠れてしまったら消すこともできずに強制終了するしかできませんでした。

    何か表示を指定のセルに近くする対処法はありますか?

  9. 匿名 より:

    先程質問したものです。
    もう一度こちらの操作方法の通常通りでやってみたらちゃんとできていました。

    何かそのファイルの中で他の改修をした際におかしくなってしまったようです。
    差し支えなければ、セルの近くに置く場合はどこをいじるのか教えて頂きますとこちらでやってみようかと思います。

    • *yuko より:

      まとめてのお返事で失礼いたします。上の方の回答と同じく、以前の更新でセルの近くを判定するコードを入れたものが、画面やウィンドウの大きさによって動作が安定しなかったのが原因のようです。デフォルト位置(画面中央表示)へ戻しましたので、お手数ですが最新版をDLし直してお試しください。

  10. 無責任なエンジニア より:

    何とかこちらに辿り着くことができました。
    大変ありがたいサイトです。

    当方でも試してみました。
    他の方のご意見にもあります通り、結合セルでは反応しません。
    単一セルの場合のみ反映します。

    併せてPC環境を変えて試してみましたが、いずれも反応しておりません。

    こちらで試した環境は、
    ・Windows 10 Enterprise + Microsoft 365 Apps for enterprise
    ・Windows 10 Professional + Microsoft Office Standard 2016

    またワークシートは既存のファイルを使用して、このサイトからダウンロードしたカレンダーモジュールを反映させております。

    当方にVisual Basicの知見がないため、ご面倒をお掛け致しますが、対処法をご教授いただけますと幸いです。
    よろしくお願い致します。

    • *yuko より:

      あたたかいお言葉、ありがとうございます! 結合セルの件、以前コメントをいただいてからできる限り環境を変えて試しているのですが、どうしても「結合セルで反応しない」現象に巡り逢うことができずにおります、すみません…。しかしながら、複数の方からのご報告があるので少なくない現象なのではと思っております。一応のご確認ですが、新規ブックで試しても反応しない、ということでよろしいでしょうか?(既存ブックだと先に組み込まれている環境が影響する場合があるため)

      現状だと手詰まり状態でして、もしもよろしかったらメールで詳細をお聞かせ願えませんでしょうか? お問い合わせのメールフォームからご連絡をいただけますと幸いです。よろしくお願いいたします。

  11. 池田 より:

    素晴らしいソフトを公開していただきありがとうございます。
    娘に依頼されて、EXCEL VBAでデータの入力・検索・修正・削除・印刷ができるコードを書いております。
    任意のセルへのカレンダー入力はできましたが、ユーザーフォームからの入力において、テキストボックスへのカレンダー入力コードがわからず、ネットで探してはみたのですが、なかなか見つかりません。
    お暇な時で結構ですので、ご指導いただけると幸甚です。
    余談ですが、娘は現在産休でじかに帰ってきております。わたくしは70歳を過ぎましたが、ボケ防止にACCESSで簡単なソフトを作っておりましたが、EXCEL VBAを知り、その素晴らしさにはまりました。

    • *yuko より:

      嬉しいお言葉、ありがとうございます。ExcelもAccessも楽しいですよね! その楽しみの一助になれて光栄です。元気な娘さん&お孫さんにお会いできること、お祈りしております。

      実は元々ユーザーフォームとテキストボックスで使うために作ったカレンダーだったのですが、セルのほうが汎用的かなと変更したので、需要をいただけて嬉しいです。ここからのカスタマイズだと工程が多いので、せっかくなのでYouTubeのほうで続きの動画として作らせていただこうかと思います。少々お待ちくださいませ。(追記:動画作成しました!)

  12. 匿名 より:

    お世話になります。
    とてもいいものをありがとうございます。仕事が捗ります。
    結合セルで使えない現象ですが、A1:A2の結合セルで使いたいときに、特定のセルででご紹介されていたコードのセル指定部分を$A$1のまま使っていると発生しました。私は初心者なので試行錯誤してどうにか$A$1:$A$2に書き換えて使用することができました。他の失敗談としては$a$1のように小文字だとできなかったです。
    私以外の初心者の助けになればと思います。
    他にはドロップダウンリストで日付を選択できるセルと併用して使いたいと思ったのですが、そのシートに保護をかけるとカレンダーが起動できませんでした。
    以上、windows10のexcel2010の報告でした。

    • *yuko より:

      【「特定セルの条件をつけているときに」結合セルが反応しない】ということだったんですね!!? 本当にありがとうございます、条件をつけない状態で試していたのでまったく再現ができずに途方に暮れていました。。おっしゃるとおり、単一セルは「$A$1」の形ですが、結合セルは「$A$1:$A$2」の形で取得されるので、結合セル用の条件を書かないと起動しません。取り急ぎ、本文にも追記させていただきます。これでほかの方も解決すると良いのですが……。

      多くの動作と掛け合わせると競合が起きてしまう可能性は十分にありますので、組み合わせてダメだったら、相性が悪かったんだなと思っていただけますとありがたいです。色々試していただいて、さらに暖かいお言葉&情報をご提供くださって本当にありがとうございます。

  13. SK より:

    YouTubeから辿り着きました。
    デフォルトで搭載してほしいくらい、デザインも機能もすべて気に入ってます!
    一点お聞きしたいのですが、以下のような使い方は出来るのでしょうか…?

    1. ユーザーフォーム上のコマンドボタンをクリックすると、このカレンダーコントロールが表示される
       ↓
    2. 日付をクリックすると、ユーザーフォーム上に設置してあるテキストボックスに日付が入る

    1については、シートモジュールにコピペするコード「Call setCalendarDateForCell(Target)」を、コマンドボタンクリック時のPrivate Sub内に貼り付ければ良さそう(?)ですが、2のやり方が分からず、、、

    VBA歴が短いので、基本的なことでしたらすみません。ご助言いただけますと幸いです。

    • *yuko より:

      ご視聴&コメントありがとうございます、気に入っていただけて嬉しいです! ユーザーフォームでもお使いいただけます。同じご要望をいただいておりまして、続きの動画を作っているところなので、できたら本文に追記いたしますね。少々お待ちくださいませ。(追記:動画作成しました!)

    • SK より:

      動画拝見しました〜!
      まさに求めていたものそのものでした!
      声も大変聞きやすく、チャプターや字幕なども便利で分かりやすく、すぐ高評価つけちゃいました!
      今後も楽しみにしております!

    • *yuko より:

      ご覧いただき、ありがとうございます! 動画はまだ始めたばかりで「こんな感じでいいのかな…?」と不安に思いながらやっているので、そう言っていただけてとっても嬉しいです!

  14. 無責任なエンジニア より:

    先日コメントした者です。
    新情報のご提供ありがとうございます。

    私の方でも結合セルの対応を試してみました。
    結合セルの場合は、結合しているセルの範囲を指定することで解決することが確認できました。

    また試した環境は以下です。
    ・Windows 10 Enterprise + Microsoft 365 Apps for enterprise
    ・Windows 10 Professional + Microsoft Office Standard 2016
    ・Windows 10 Professional + Microsoft Office Professional Plus 2021

    この度は大変お世話になりました。
    ありがとうございました。

    • *yuko より:

      フィードバックありがとうございます! 解決して安心しました~!!

  15. 事務職 より:

    活用させていただいてます!

    フォーム起動時に年数が1899年の12月となってしまい、更に12月の12の部分が選択された状態で起動してしまうのですが、何が原因なのでしょうか?

    • *yuko より:

      コメントありがとうございます。おそらく、なんらかの原因で数値の0をシリアル値と判定しているものと思われます。該当のブックで、セルにゼロが入っていて表示形式が日付、のような設定になっていないかご確認ください。オプションの詳細設定で「ゼロ値のセルにゼロを表示する」のチェックが外れていると、0が入っていても表示されません。
      また、月のコンボボックスが選択されているのは仕様です。操作可能な「年」「月」コンボボックス、または月移動のスピンボタンのどれかにフォーカスがあたって起動するので、便宜上「月」にしています。コンボボックスのフォーカスは文字が反転して嫌な場合は、VBEのオブジェクト表示でスピンボタンの「TabIndex」プロパティを「0」にすると、起動時のフォーカスをスピンボタンにできます。

  16. Ohide より:

    初めましてOhideと申します。
    まだVBAを始めて2ヶ月の者ですが、カレンダーからの日付選択がしたくこちらのサイトに辿り着きました。
    動画は解りやすい解説で大変有難う御座います。
    それで質問なのですが、CalendarSetup_221205.zipをVBAにインポートし祝日対応(ネット接続版?)は
    カレンダーに反映するのですが、ネット接続せず休日シート版でやりたく思い後日のブログでupされています
    プログラムを入れたのですが途中で停止してしまいます。
    DLしましたプロシージャと、”前回書いてるはず”のプロシージャの内容が違う為?か上手くいきません。
    助言をいただけますでしょうか。 よろしくお願いします。

    • *yuko より:

      はじめまして、コメントありがとうございます。オフラインの休日シート版というのは、大昔に書いたこの記事(2014/8/7公開)のことですね。これは、その前の記事(2014/8/4公開)で紹介しているコードに追記する前提で書いています。過去のものは「カレンダーをフォームからすべて自作してみよう」というコンセプトで書いたのですが、その後だいぶ経ってから「難しいところはわからなくてもいいから、かんたんシンプルにサクッと使える」方向性で2022年に書き直したのが、このページです。そのため、過去のものとコードが異なっています。

      オンラインAPI版があれば休日シート版は需要ないかなと思って書かなかったのですが、掘り起こしてチャレンジしていただいてありがとうございます。シート構造は当時の記事の通り作っていただいて、このページからDLできるバージョンへの対応コードを下に書いておきます。「F_Calendar」モジュール内の「setCalendar」プロシージャへ、ハイライト部分を追加してください。

      Private Sub setCalendar()
        '## カレンダーの作成と表示
        '略
          
        For i = 1 To 37 'ラベルの初期化
          With Me("lbl_day" & i)
            .Caption = "" 'キャプション
            .BorderStyle = fmBorderStyleNone '枠なし
            .BackColor = Me.BackColor 'フォームと同じ背景色へ
            Select Case i Mod 7
              Case 1
                .ForeColor = vbRed '日曜は文字色を赤
              Case 0
                .ForeColor = vbBlue '土曜は文字色を青
              Case Else
                .ForeColor = vbBlack 'その他(平日)は文字色を黒
            End Select
          End With
        Next
        
        Dim n As Long '月はじめの位置用変数
        n = Weekday(yy & "/" & mm & "/" & 1) - 1 'その月の1日の曜日番号に、-1したもの
        
        Dim endDay As Long '月末日用変数
        endDay = day(DateAdd("d", -1, DateAdd("m", 1, yy & "/" & mm & "/" & "1"))) '算出
        
        Dim ws_h As Worksheet '休日情報のシート用変数
        Set ws_h = Sheets("休日リスト")
        Dim fnd As Range, hasData As Boolean, row_h As Long
        Set fnd = ws_h.Columns("A").Find(yy) '年を検索
        If Not fnd Is Nothing Then '年が見つかったら月のチェック
          row_h = fnd.Row + mm - 1
          If ws_h.Cells(row_h, 2) = mm Then hasData = True '該当月があったらフラグを立てておく
        End If
        
        Dim tgtDay As Date '日付生成用変数
        For i = 1 To endDay '1日から月末日まで
          tgtDay = yy & "/" & mm & "/" & i '該当日付生成
          With Me("lbl_day" & n + i) '該当のラベルに対して
            .Caption = i '日を入れる
            If tgtDay = Date Then '今日なら
              .BorderStyle = fmBorderStyleSingle '枠を付ける
            End If
            If tgtDay = g_cldCurrentDate Then 'TextBoxの日と同じなら
              .BackColor = RGB(200, 200, 200) '背景色を付ける
            End If
            If hasData Then '休日シートに該当月があれば
              If ws_h.Cells(row_h, i + 2) = 1 Then .ForeColor = vbRed '該当日が1なら文字色を赤
            End If
          End With
        Next i
      End Sub
      

      なお、当時の記事にもあるように「休」なら赤、「出」なら黒にしたい場合は上の47~49行目を以下のようにしてください。

      If hasData Then '休日シートに該当月があれば
        If ws_h.Cells(row_h, i + 2) = "休" Then .ForeColor = vbRed '該当日が休なら文字色を赤
        If ws_h.Cells(row_h, i + 2) = "出" Then .ForeColor = vbBlack '該当日が出なら文字色を黒
      End If
      
  17. 匿名 より:

    こんばんはOhideです。
    *yukoさん過去のプログラムなのに、迅速な対応誠にありがとうございます。
    上記のプログラムで無事!いけました!!
    有難く使わせて頂きます。
    また勉強させて頂きますので宜しくお願い致します。

    • *yuko より:

      フィードバックありがとうございます! ちゃんと動いてよかったです~!!

  18. ちと より:

    こんにちは。Windows10へとver.が変更になり、DateAndTimePickerが使えなくなり、困り果ててこちらへたどり着きました。
    とても詳しく説明されているので利用させていただきました。
    ご説明の通りにコピーさせていただき、カレンダー表示したいエクセルのセルをダブルクリックしました。

    「コンパイルエラー:プロジェクトまたはライブラリーがみつかりません」表示され、
    「M_CalendarSetting」
    Public Sub setCalendarDateForCell(ByVal tgtRange As Range) ←黄色く表示
    ‘## カレンダーで選択した日付をテキストボックスに入力する
    If IsDate(tgtRange.Cells(1.1).Value) = False Then ‘日付が入ってなければ
    g_cldCurrentDate = Date ‘今日の日付を格納 ← Date が青く表示

    VBを最近勉強しはじめたばかりで何がたりないのかわかりません。
    初級の初級とおもわれますがご説明いただけますでしょうか。
    よろしくお願いいたします。

  19. ちと より:

    丁寧な回答ありがとうございます。
    参考に頂いた内容を検証してみましたがうまくできませんでした。
    やはり、PC環境がうまくできていないよう気がします。
    Windows10の再インストールをしなおしてみます。
    ありがとうございました。

    • *yuko より:

      フィードバックありがとうございます。OSのほか、Officeの修復や再インストールも効果があるかもしれません。また、新規ブックで動くのであれば、既存ブックに組み込まれている環境との相性の問題も考えられます(すでにお試しでしたらすみません)。解決できることをお祈りしております!

  20. 匿名 より:

    素敵なプログラムを公開頂きありがとうございます。
    和暦表示にするにはどこを変更したら良いか教えていただけますでしょうか。
    (「ExcelVBAでカレンダーコントロールを自作する」の記事も拝見しましたが分からず恐縮です)

    • *yuko より:

      コメントありがとうございます。こちらも昔の記事にあったものですね。ちょっと修正箇所が多かったので、本文のほうに追記しましたのでご覧ください。

    • 匿名 より:

      早々のご対応頂き感謝申し上げます。
      今後の業務に活かさせて頂きたく存じます。

    • *yuko より:

      フィードバックありがとうございます! お役にたてて光栄です~!

  21. すー より:

    素晴らしいツールを公開していただきありがとうございます。
    カレンダーから日付を選択できるようになって業務の効率化に大変役立ってます。

    1点教えて頂きたいのですが、カレンダーの下部に今日の日付を入力できるようなボタンを追加するにはどのようにしたら出来ますでしょうか?ご教授をお願いいたします。

    • *yuko より:

      嬉しいお言葉、ありがとうございます。現在は、セルが空だった場合は今日の日付に枠が付きますが、それとは別に今日の日付専用のボタンがほしいということでしょうか? 今日ではない年月が表示されているときでも今日の日付を入れたいという意図ですかね? 今日の日付専用ボタンもできますが、別の年月が表示されているときに今月へ移動するボタン、ではどうでしょうか?

  22. 匿名 より:

    回答有難うございます。
    よく考えればカレンダーとは別にボタンを追加して今日の日付を入力するマクロを設定するだけでした。お騒がせしました。

    • *yuko より:

      フィードバックありがとうございます。自己解決がいちばん勉強になると思ってるので、答えが出て嬉しいです!

  23. hana より:

    質問させていただきます。
    初心者です。
    ダブルクリックではなく、シングルクリックでカレンダーを表示させるには
    どうしたらよいでしょうか?

    ☆☆動画も拝見しました。
    なかなかピンと来るものが見当たらず困っていたのですが、
    こちらを見つけた時は「コレコレ!」と思わず声が出てしまいました!
    まさに求めていたものでした!
    わかりやすくて初心者の私にも上手くできて感激しました。
    ありがとうございます!

    • *yuko より:

      コメント&嬉しいお言葉ありがとうございます。

      「シートモジュールにコピペするコード」の最初の行に書いてある「Worksheet_BeforeDoubleClick」は、「ワークシートをダブルクリックしたとき」を意味しているのですが、利用できるイベントはあらかじめ決まっていて、「Worksheet_BeforeSingleClick」というものはありません。代わりとするならば「Worksheet_SelectionChange(選択セルが変更されたとき)」が考えられます。以下のように書きます。

      Private Sub Worksheet_SelectionChange(ByVal Target As Range)
        Call setCalendarDateForCell(Target)
      End Sub
      

      ただしこのイベントはシングルクリックで選択したときはもちろん、キーボード操作でセルを移動したときもその都度実行されてしまうのでご承知ください。「特定のセルだけカレンダーを起動」するカスタマイズを加えたほうがよいと思います。

  24. masa より:

    分かりやすい解説・動画で勉強させていただきありがとうございます。
    質問させていただきたいのですが,カレンダーからテキストボックスに日付を入力した際にテキストボックス内の表示も和暦にするにはどうしたらいいのでしょうか?
    また、日付の後に曜日を追加することも出来るのでしょうか?
    大変恐縮ですが,御指導のほどよろしくお願いします。

    • *yuko より:

      コメントありがとうございます。「テキストボックス用にコピペするコード」として、「M_CalendarSetting」モジュールに追加した「setCalendarDateForTextBox」プロシージャのハイライト部分を以下のようにしてみてください。

      Public Sub setCalendarDateForTextBox(ByVal tgtTxb As MSForms.TextBox)
        '## カレンダーで選択した日付をテキストボックスに入力する
        
        If IsDate(tgtTxb.Value) = False Then '日付が入ってなければ
          g_cldCurrentDate = Date '今日の日付を格納
        Else
          g_cldCurrentDate = tgtTxb.Value 'テキストボックスの日付を格納
        End If
        
        F_Calendar.Show 'カレンダーを開く
        
        If g_isCldCancel = True Then Exit Sub 'キャンセル(バツボタンで閉じられた)なら終了
        tgtTxb.Value = Format(g_cldPickedDate, "ggge年m月d日") 'クリックされた日付を上書き
      End Sub
      

      なお、曜日も表示したい場合は以下のようにしてください。

      Public Sub setCalendarDateForTextBox(ByVal tgtTxb As MSForms.TextBox)
        '## カレンダーで選択した日付をテキストボックスに入力する
        
        Dim tmp As String
        tmp = tgtTxb.Value 'テキストボックスの値を変数に格納
        If InStr(tmp, "(") <> 0 And InStr(tmp, ")") <> 0 Then 'カッコがあったら
          tmp = Left(tmp, Len(tmp) - 3) '後ろから3桁(曜日)を除去
        End If
        
        If IsDate(tmp) = False Then '日付と判定されなかったら
          g_cldCurrentDate = Date '今日の日付を格納
        Else
          g_cldCurrentDate = tmp '日付を格納
        End If
        
        F_Calendar.Show 'カレンダーを開く
        
        If g_isCldCancel = True Then Exit Sub 'キャンセル(バツボタンで閉じられた)なら終了
        tgtTxb.Value = Format(g_cldPickedDate, "ggge年m月d日(aaa)") 'クリックされた日付を上書き
      End Sub
      

      和暦+曜日だと文字数が多くなるのでテキストボックスの横幅は広めにしたほうが良さそうです。お試しください。

    • masa より:

      素早い対応と回答ありがとうございました!
      テキストボックス内の表示も曜日も無事にいけました!
      しっかりと業務に活用させていただきます!

    • *yuko より:

      ちゃんと動いてよかったです~! フィードバックありがとうございました!!

  25. KOMI より:

    こんにちは、カレンダーコントロールを探していて辿り着きました。
    年の表示を「yyyy(ggge)」に変更して使っています。
    とても有用なコードを提供して頂き感謝します。

    別件ですが、
    結合セルを認識しない件については

    Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    If Target.Address “$A$1:$B$2” Then Exit Sub ‘A1:B2の結合セル以外なら終了
    Call setCalendarDateForCell(Target)
    End Sub

    ではなく

    Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
    If Intersect(Target, Range(”A1:B2”)) Is Nothing Then Exit Sub ‘A1:B2の結合セル以外なら終了
    Call setCalendarDateForCell(Target)
    End Sub

    で行えないでしょうか
    Target.Addressはうまく拾えない事がある様な記事を見た事があって私はIntersectを使用しています。
    記事があれば良いのですが失念しており見つけられなかったです。
    ご参考までに

    • *yuko より:

      コメント&情報ありがとうございます。こんな方法もあるのですね! たいへん勉強になりました。ありがたく本文にも追記させていただきます。

  26. 123 より:

    素晴らしいプログラムを公開して頂きありがとうございます。
    当方初心者でございます。
    上記のやり方で、インポートさせて頂いたのですが、やり方がよくないのか
    年を選択するコンボボックスが1896年から1902年しか選択できないようになってしまいます。
    お忙しいところ申し訳ございませんが、教えて頂きたく思います。

    • *yuko より:

      コメントありがとうございます。おそらく、なんらかの原因で数値の0をシリアル値と判定しているものと思われます。該当のブックで、セルに0が入っていて表示形式が日付、のような設定になっていないかご確認ください。オプションの詳細設定で「ゼロ値のセルにゼロを表示する」のチェックが外れていると、0が入っていても表示されません。

  27. コジタケ より:

    こんにちは

    このようなサイトを作成していただきありがとうございます。
    質問なんですが、インターネットを接続できない職場環境で、外部からのダウンロードしたものを職場のパソコンに入れることができないのでダウンロードが利用出来なくて困っています。

    今回のようなカレンダーを手入力で入れて行きたいのですがインポートするデータのマクロを見せて頂けると助かります。

  28. タケダ より:

    こんにちは、
    この度エクセルで日付入力ミスを解消したいと思いこちらのカレンダーアプリを利用させて頂くことになりました。
    特定の列だけで動くコードについてですが
    例えば「C列4行目からC列任意の行まで」
    または「C列4行目からC列最終行まで」で動かしたいのですがコードを教えていただけませんでしょうか。
    昨日、今村様の書籍「ExcelVBAユーザーフォーム&コントロール」を取り寄せ購入してきたのですが、こちらについての記載を見つけることが出来ませんでした。
    VBA初心者ですが何卒ご対応の程よろしくお願いします。

    • *yuko より:

      コメントありがとうございます。「C列4行目からC列任意の行まで」は以下で、

      Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        Dim n As Long
        n = 10 '任意の行
        If Target.Column = 3 And 4 <= Target.Row And Target.Row <= n Then
          Call setCalendarDateForCell(Target)
        End If
      End Sub
      

      「C列4行目からC列最終行まで」は以下のように書きます。

      Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        If Target.Column = 3 And 4 <= Target.Row Then
          Call setCalendarDateForCell(Target)
        End If
      End Sub
      

      また、「ExcelVBA ユーザーフォーム&コントロール 実践アプリ作成ガイド」に収録されているカレンダーコントロールはフォームを使ったアプリ内での利用方法を記載しているので、今回のようなご要望には添えずに申し訳ありません。フォームを扱えるとExcelの利用幅が広がりますので、せっかくなので、ぜひご活用くださいね。

  29. タケダ より:

    早々のご対応ありがとうございます♪
    仰る通り、フォームを扱える様になるとかなり業務改善になるので書籍とYouTubeを参考に勉強してみます。
    今後も機会がありましたら、ご指導宜しくお願い致します。

    • *yuko より:

      フィードバックありがとうございます! ぜひぜひ、がんばってみてください~!

  30. あかねこ より:

    こんばんは
    一番 最近のコメントを送られた方に似ているのですが
    複数の範囲指定の場合 どのように指定すればいいのでしょうか?
    例えば
    「C列4行目からC列10行と E列4行目からE列10行」
    VBA初心者なので 参考にさせてもらってます
    よろしくお願いします。

    • *yuko より:

      こんにちは、コメントありがとうございます。範囲が多いと条件が長くなるので、以下のように2つに分けちゃうと良いと思います!

      Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        If Target.Column = 3 And 4 <= Target.Row And Target.Row <= 10 Then 'C列4行目からC列10行
          Call setCalendarDateForCell(Target)
        End If
        If Target.Column = 5 And 4 <= Target.Row And Target.Row <= 10 Then 'E列4行目からE列10行
          Call setCalendarDateForCell(Target)
        End If
      End Sub
      
  31. あかねこ より:

    早急のご対応ありがとうございます。

    「ary = Array(“$C$4”, “$C$5”, “$C$6”, “$C$7”, “$C$8”, “$C$9”,...」と
    気の遠くなる 打込みをしてたので助かりました。

    電子版ですが書籍の方も買わせて頂きました。
    参考にしたいと思います。
    ありがとうございました。

    • *yuko より:

      フィードバックありがとうございます、確かに気が遠くなりますね…! あの後さらに考えてみたら、下記のコードのほうが断然スマートにできることに気づいたのでお試しください。本文も直しておきました。書籍のほうもありがとうございます! 嬉しいです!

      Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        If Intersect(Target, Range("C4:C10, E4:E10")) Is Nothing Then Exit Sub 'C4:C10, E4:E10範囲以外なら終了
        Call setCalendarDateForCell(Target)
      End Sub
      
  32. ジン より:

    探し求めていたものがここにありました!ありがとうございました!
    大変恐縮なのですが、質問がございます。
    結合されている別々のセルをダブルクリックした時、用途の違う別々のカレンダーを表示したいのですが、色々試してみたののできませんでした。
    なにか方法はございますでしょうか?

    あと私はユーザーフォームの表示場所を下記で指定してみました。
    Private Sub UserForm_Initialize()
    ‘## フォーム読込時

    StartUpPosition = 0
    Top = 200
    Left = 500
    ‘ユーザーフォームの表示場所指定

    • *yuko より:

      コメントありがとうございます。「用途の違う」という部分を、具体的にどのようにしたいのか詳しくお聞かせ願えたらと思います。別デザイン(?)のカレンダーを用意して、「Aセルから起動したらAデザインのカレンダー、Bセルから起動したらBデザインのカレンダー」のようなことでしょうか?

    • ジン より:

      お返事いただきありがとうございます。

      例えば、A1のセルをダブルクリックすると ±3年のカレンダーを表示(来客時)
          B1のセルをダブルクリックすると 現在から-100年のカレンダーを表示(誕生日)
      のようなものですが・・・
      宜しくお願い致します

    • *yuko より:

      なかなかおもしろい使い方ですね。F_CalenarモジュールのUserForm_Initializeプロシージャを、以下のハイライト部分のように書き換えていただけると良いのではないかと思います。A1セルなら±3年、B1セルなら-100年~今年、それ以外だったらデフォルトとして±5年という例で書いてあります。

      Private Sub UserForm_Initialize()
        '## フォーム読込時
        
        Dim i As Long '汎用変数
        g_isCldCancel = False 'キャンセルフラグをFalseにしておく
        
        If Not Intersect(ActiveCell, Range("A1")) Is Nothing Then 'A1セルだったら
          For i = -3 To 3 '前後3年分の年をリストに追加
            Me.cmb_year.AddItem Year(g_cldCurrentDate) + i
          Next i
        ElseIf Not Intersect(ActiveCell, Range("B1")) Is Nothing Then 'B1セルだったら
          Dim startYear As Long: startYear = Year(Date) - 100 '100年前を取得
          If Year(g_cldCurrentDate) < startYear Then startYear = Year(g_cldCurrentDate) '取得年のほうが前なら置き換え
          Dim endYear As Long: endYear = Year(Date) '今年を取得
          If endYear < Year(g_cldCurrentDate) Then endYear = Year(g_cldCurrentDate) '取得年のほうが後なら置き換え
          For i = startYear To endYear '年をリストに追加
            Me.cmb_year.AddItem i
          Next i
        Else 'それ以外のセルだったら(デフォルト)
          For i = -5 To 5 '前後5年分の年をリストに追加
            Me.cmb_year.AddItem Year(g_cldCurrentDate) + i
          Next i
        End If
        
        For i = 1 To 12 '月をリストに追加
          Me.cmb_month.AddItem i
        Next i
          
        Me.cmb_year.Value = Year(g_cldCurrentDate) '年を指定
        Me.cmb_month.Value = Month(g_cldCurrentDate) '月を指定
      End Sub
      

      -100年~今年と固定すると、あらかじめ入っていた日付がその範囲外にあったときにエラーになってしまうので、そのあたりのエラー処理を12~15行に入れてあります。お試しください。

    • ジン より:

      ご返信ありがとうございます。
      とても助かります、色々と自身でも勉強して応用していきたいと思います!
      時間を割いていただき本当にありがとうございました。

    • *yuko より:

      お役に立てて光栄です! いろいろカスタマイズしてみてくださいね。

  33. みのりん より:

    大変使いやすく、自分のイメージにぴったりのカレンダーです。提供して頂き心から感謝しております。
    下記教えて頂きたいことがあります。
    日付を文字列で出力させることは可能でしょうか?
    例えば、2024/02/20 → ’2024ー02ー20 です。

    • *yuko より:

      コメント&嬉しいお言葉、ありがとうございます。表示だけで良ければセルの書式設定から変更できますが、頭にシングルクォーテーションを付けた文字列出力ということですよね。M_CalendarSettingモジュールのsetCalendarDateForCellプロシージャの以下のハイライト部分を変更してみてください。

      Public Sub setCalendarDateForCell(ByVal tgtRange As Range)
        '## カレンダーで選択した日付をセルに入力する
      
        If IsDate(tgtRange.Cells(1, 1).Value) = False Then '日付が入ってなければ
          g_cldCurrentDate = Date '今日の日付を格納
        Else
          g_cldCurrentDate = tgtRange.Cells(1, 1).Value 'セルの日付を格納
        End If
      
        F_Calendar.Show 'カレンダーを開く
      
        If g_isCldCancel = True Then Exit Sub 'キャンセル(バツボタンで閉じられた)なら終了
        tgtRange.Value = "'" & Format(g_cldPickedDate, "yyyy-mm-dd") 'クリックされた日付を上書き
      End Sub
      

      余談ですが、出力で「’」を付けちゃったら呼び出すときに「’」を外さないと日付として認識できないかと思ったら、そのまま動きますね。VBAはこういうところけっこう融通が利いて楽ですね。

  34. みのりん より:

    お忙しい中、早々にご対応頂き有難うございました。
    私の願っていた通りの動きになり感激しております。私は今業務効率化でエクセルのデータ資産をSQLiteに移行出来ないか試行錯誤しているところです。
    日付の表示形式をどうしても文字列で取得したかったので、コードを色々弄ってみましたが旨く行かず、ご教示お願いいたしました。コードの変更も大変勉強になりました。
    これで、また一歩前に進む事が出来ます。
    本当に有難うございました。

    • *yuko より:

      フィードバックありがとうございます、私もデータベース使うので、そっち方面のご要望かなと思ってました! 一助になれて光栄です。がんばってくださいね!

  35. ターコイズ より:

    すごく参考になりました。ありがとうございます。

    一つ質問なのですが、フォームから特定セルに日付を入力できるようになったのですが、それが日付と認識されてないのか、別セルの関数が反応しません。また、表示形式もm/dに変更したいのですがマクロから変更されません。
    マクロ初心者でわからないことが多いので変なことを言ってるかもしれません。教えていただけると助かります。

    • *yuko より:

      コメントありがとうございます。マクロは年月日が正しく特定できる日付データをセルに渡すのが目的で、渡されたデータを日付と扱うか、どんな表示形式にするのかは、セルの書式設定に依存します。そちらの設定をお確かめください。

      1点もしやと思ったのは、このカレンダーはセルのダブルクリックで起動する性質上、日付挿入後にセルが編集状態になります。セルが編集中だと、そこを参照しているほかのセルが正常に表示されない場合もあるかもしれません。シートモジュールに書くプロシージャに以下の1文を追記すると、編集状態にならずに日付挿入できるようになるので、試してみてください。本文にも追記しておきました。

      Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
        Cancel = True
        Call setCalendarDateForCell(Target)
      End Sub
      
  36. まさ より:

    本当にわかりやすくて、ものすごく助かりました!
    本当にありがとうございます

    • *yuko より:

      こちらこそ、とっても嬉しいコメント、ありがとうございます。励みになります!

  37. 超初心者です。 より:

    エクセルVBAの超初心者ですが、カレンダーをいれるところまでできました。ありがとうございました。
    質問させてください。
    シートのセルB2にカレンダーで「○月○日」と表記できるようになったのですが、
    もう一つ別のセルC1に、「○月○日の週間予定」というセルがほしいです。
    B2にカレンダーで日付を入力すると、C1も自動でB2と同じ日付で「○月○日の週間予定」という風に
    かわってほしいのですが、何か方法はございますでしょうか。

    • *yuko より:

      コメントありがとうございます。
      C1セルに=MONTH(B2)&"月"&DAY(B2)&"日の週間予定"と入力してみてはいかがでしょうか?

    • 超初心者です。 より:

      なんと!できました!ありがとうございました。

    • *yuko より:

      フィードバックありがとうございます。ご期待に添えたみたいで良かったです~!

  38. VBA初心者 より:

    カレンダー機能を探してこの記事に辿り着きました。

    Zipファイルをダウンロードしてフォームと標準モジュールはインポートできたのですが、
    起動したいシートに起動用のコードをコピペしてもカレンダーが出てきません。
    (セルがアクティブになるだけで通常のダブルクリックの動作になってしまいます…)

    皆さんできているようなのでおそらく当方が悪いような気がしますが、
    他のマクロは問題なく起動するので謎が深まるばかりです。
    差し支えなければ解決方法をご教示いただけると幸いです。

    • *yuko より:

      コメントありがとうございます。シートモジュールにコピペするコードは「イベントプロシージャ」という種類で、「シートがダブルクリックされた」動作をきっかけに自動で実行される特徴を持ちます。通常のダブルクリックの動作になるということは、コードが「イベントプロシージャ」と認識されていないのだと思います。

      コピペされているのであれば記述ミスなどはないと思いますが、コピペの経由途中でなんらかの変換が挟まってしまい、余計なスペースが挿入されたり、スペースが全角に変換されたり、変なところで改行されたり、といった現象はないでしょうか?

      また、正しい位置に正しい記述で入力されていても、入力直後は一時的にイベントプロシージャだと認識されないことが稀にあります。その場合はいったんExcelを保存、終了して起動しなおしたり、PCを再起動することで認識されることがあります。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)

YouTubeでQ&Aコンテンツを企画しています

運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。