空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

Unionで纏められたRange内のセルにVBAでアクセスする(Excel)

あまり使う事はないような気がするが、複数のセル範囲の集合をひとつのRangeとした時、そのRange内のデータにどうやってアクセスするのか?やってみました。
複数のセル範囲が不連続の場合のアクセス方法を調べることが目的です。

Unionで纏める記事はそれなりにあるようですが、纏めた後にどうやってアクセスするのか書かれているサイトは多くはないようです。

まずは、以下のようなデータを用意し、赤で囲まれた部分と青で囲まれた部分を対象のRangeとすることとします。

f:id:Z1000S:20190301221055j:plain
サンプルデータ

結論から書くと

対象Range.Areas(n).Cells(row, col)

といった指定をすることで出来ます。

ポイントとなるのは、Range.Areas プロパティです。
これは、「複数領域選択範囲内のすべての範囲を表す**Areas** コレクションを返します。 読み取り専用です。」と説明されています。

複数のセル範囲の集合をひとつのRangeとして設定する

Unionメソッドを使用し、下記のように使用します。

Set r = Union(Sheet1.Range("B2:D4"), Sheet1.Range("F3:G4"))

Range("B2:D4") <===で囲まれた範囲
Range("F3:G4") <===で囲まれた範囲

セル範囲数を調べる

使うのはAreas.Count プロパティです。

下記コードでは、

r.Areas.Count

の部分が該当し、今回の場合、2が返ってきます。

各セル範囲のアドレスを調べる

使うのは、Range.Address プロパティです。
セル範囲は、Areasに1から始まるインデックスにより指定します。
下記コードでは、

r.Areas(k).Address(False, False)

の部分が該当します。
今回の場合、
で囲まれた範囲がArea(1)
で囲まれた範囲がArea(2)
となり、
r.Areas(1).Address(False, False)は
B2:D4
r.Areas(2).Address(False, False)は
F3:G4
が返ります。
Unionで指定した順番に返ってくるようです。(そうでないと困ります。)
ちなみに、Unionした全体の範囲は

r.Address(False, False)

で取得でき、
B2:D4,F3:G4
と返ってきます。

各セル範囲の行数、列数を調べる

r.Areas(n)が通常のRangeを返すので、それぞれ以下のように指定して取得することが出来ます。

r.Areas(n).Rows.Count
r.Areas(n).Columns.Count

セルの値を取得する

Range.Cells プロパティを使用して、指定したセルにアクセスできます。

r.Areas(n).Cells(i, j).Value

ここで、Cellsに指定する行、列の値は、対象Range(各Area(n)とも)の左上のセルを1行目、1列目とした相対的指定になるようで、Cells(1,1)といった指定を行うようです。
これに関しては、サンプルコードと実行結果を見ていただいた方がわかりやすいと思います。
さらに、対象Rangeの行数、列数を超える値をCellsに指定してもエラーにはならないようです。
指定方法を間違えると、対象Rangeに含まれないセルにアクセスすることになるので注意が必要です。
例えば、

? r.Areas(1).Cells(1, 4).Value

とすると
E2
と出力され、Area(1)の列は、B~Dであるにもかかわらず、Area(1)には含まれないセルE2が参照することが出来てしまいます。

サンプルコード

Public Sub AccessToUnionRange()

    Dim r   As Range
    Dim sLine   As String
    Dim i   As Long
    Dim j   As Long
    Dim k   As Long

    '複数のRangeをUnionで纏める
    Set r = Union(Sheet1.Range("B2:D4"), Sheet1.Range("F3:G4"))

    Debug.Print "エリア数:" & r.Areas.Count
    Debug.Print "全エリア:" & r.Address(False, False)

    For k = 1 To r.Areas.Count
        Debug.Print "エリア" & CStr(k) & ":" & r.Areas(k).Address(False, False)
    Next k

    For k = 1 To r.Areas.Count
        Debug.Print "----- Area" & CStr(k) & " -----"

        For i = 1 To r.Areas(k).Rows.Count
            sLine = CStr(i) & ":"

            For j = 1 To r.Areas(k).Columns.Count
                sLine = sLine & vbTab & r.Areas(k).Cells(i, j).Value
            Next j

            Debug.Print sLine
        Next i
    Next k

End Sub

実行結果

Call AccessToUnionRange
エリア数:2
全エリア:B2:D4,F3:G4
エリア1:B2:D4
エリア2:F3:G4
----- Area1 -----
1: B2 C2 D2
2: B3 C3 D3
3: B4 C4 D4
----- Area2 -----
1: F3 G3
2: F4 G4

最後に

Areas(n)を指定することで、個別のセル範囲を特定することが出来、かつRange.Areas(n)がRangeオブジェクトと分かってしまえば、それほど難しくなく処理を書けそうです。

Excelワークシートに指定フォルダ(サブフォルダを含む)から画像を読み込んで貼り付けてみた

もうすぐ3月です。
私のいる会社では、月末近くになると年度末の棚卸しがあります。

担当の方がデジカメで写真を撮っては、Excelのワークシートに
ちまちまと貼り付けてはサイズと位置を調整して・・・

面倒くさそうです。(私はその作業に関しては部外者なので関係ないので、他人事)

それ(棚卸)に、完璧に対応するのはとても無理だけど、
少しだけ楽(手抜き?)が出来るかもしれない処理を作ってみました。

やることは、ざっくり言えば、画像の貼り付けとリサイズの(もう少し少ない?)自動化。

もうちょっと詳しく言えば

  1. 画像のあるフォルダを指定出来ること
  2. 画像は、指定したフォルダのサブフォルダを含めて抽出できること
  3. 画像の並びは、ファイル名ではなく、ファイルのフルパスで昇順とすること
  4. 画像を貼り付ける先頭セルを指定できること
  5. 画像はセル1個につき1ファイルとすること
  6. 貼り付けた画像は、貼り付けるセルの大きさに一致させること(オリジナルと縦横の比率が変わってもOKということ)

といった感じでしょうか。

Option Explicit

'参照設定(FileSystemObject用)
'Microsoft Scripting Runtime

'貼り付けする画像があるフォルダ
Private Const TARGET_FOLDER     As String = "C:\Datas\棚卸写真"

'画像を貼り付けるシート名
Private Const TARGET_SHEET_NAME As String = "Sheet1"

'画像を貼り付ける最初のセルアドレス
Private Const IMAGE_PASET_BEGIN_ADDRESS As String = "B1"

'貼り付けする画像の拡張子
Private Const TARGET_EXT        As String = ".png"


Public Sub addPictures()

    Dim r               As Range
    Dim sTargetPaths()  As String
    Dim i               As Long

    ReDim sTargetPaths(0)

    '指定フォルダにある指定拡張子の画像のパス一覧を取得
    Call getTargetPaths(TARGET_FOLDER, sTargetPaths)

    '画像のパスを昇順で並べ替え
    Call sortArrayList(sTargetPaths)

    '画像を貼り付ける最初のセル
    Set r = ThisWorkbook.Worksheets(TARGET_SHEET_NAME).Range(IMAGE_PASET_BEGIN_ADDRESS)

    '指定のセルに画像を貼り付け
    Call insertImage(sTargetPaths, r)
'    Call insertImage(sTargetPaths, r, 1)

End Sub


'指定フォルダにある指定拡張子の画像のパス一覧を取得
Private Sub getTargetPaths(ByVal sSrcFolder As String, ByRef sTargetPaths() As String)

    Dim fso     As FileSystemObject
    Dim fl      As Folder
    Dim f       As File
    Dim sTargetFolder   As String
    Dim lElements       As Long

    Set fso = New FileSystemObject

    If Not fso.FolderExists(sSrcFolder) Then
        Exit Sub
    End If

    For Each fl In fso.GetFolder(sSrcFolder).SubFolders
        'サブフォルダがあれば、再帰処理
        Call getTargetPaths(fl.Path, sTargetPaths)
    Next fl

    For Each f In fso.GetFolder(sSrcFolder).Files
        '拡張子チェック
        If Right$(LCase(f.Name), Len(TARGET_EXT)) = TARGET_EXT Then
            If Right$(sSrcFolder, 1) = "\" Then
                sTargetFolder = sSrcFolder
            Else
                sTargetFolder = sSrcFolder & "\"
            End If

            lElements = UBound(sTargetPaths)

            If lElements > 0 Then
                lElements = lElements + 1

                ReDim Preserve sTargetPaths(lElements)

                sTargetPaths(lElements) = sTargetFolder & f.Name
            ElseIf lElements = 0 Then
                If sTargetPaths(lElements) = "" Then
                    sTargetPaths(lElements) = sTargetFolder & f.Name
                Else
                    lElements = lElements + 1

                    ReDim Preserve sTargetPaths(lElements)

                    sTargetPaths(lElements) = sTargetFolder & f.Name
                End If
            End If
        End If
    Next f

End Sub

Private Sub sortArrayList(ByRef sDatas() As String)

    Dim ws  As Worksheet
    Dim sortRange   As Range
    Dim vDatas      As Variant
    Dim i           As Long

    With ThisWorkbook.Worksheets.Add
        .Visible = xlSheetHidden

        Set sortRange = .Range("A1").Resize(UBound(sDatas) + 1)

        sortRange = WorksheetFunction.Transpose(sDatas)
        
        .Sort.SortFields.Clear
        .Sort.SortFields.Add Key:=sortRange, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal

        With .Sort
            .SetRange sortRange
            .Header = xlGuess
            .MatchCase = False
            .Orientation = xlTopToBottom
            .SortMethod = xlPinYin
            .Apply
        End With

        vDatas = sortRange

        For i = LBound(vDatas) To UBound(vDatas)
            sDatas(i - 1) = CStr(vDatas(i, 1))
        Next i

        Application.DisplayAlerts = False
        .Delete
        Application.DisplayAlerts = True
    End With

End Sub

'画像を貼り付け
'
'   sTargetPaths()  :貼り付ける画像のパスを格納した配列
'   r               :画像を貼り付ける最初のセル
'   lIntervalRow    :画像を貼り付ける間隔(デフォルト0。省略可)
'
Private Sub insertImage(ByRef sTargetPaths() As String, ByRef r As Range, Optional ByVal lIntervalRow = 0)

    Dim rng As Range
    Dim fso As FileSystemObject
    Dim i   As Long

    Set fso = New FileSystemObject

    For i = 0 To UBound(sTargetPaths)
        '画像を貼り付けるセルの位置、サイズ情報取得用
        Set rng = r.Offset((lIntervalRow + 1) * i)

        Call r.Parent.Shapes.AddPicture( _
                Filename:=sTargetPaths(i), _
                LinkToFile:=False, _
                SaveWithDocument:=True, _
                Left:=rng.Left, _
                Top:=rng.Top, _
                Width:=rng.Width, _
                Height:=rng.Height)

        rng.Offset(, 1).Value = fso.GetFileName(sTargetPaths(i))
    Next i

End Sub


画像データはこんな感じ

f:id:Z1000S:20190227173726j:plain
おにぎりフォルダ
f:id:Z1000S:20190227173737j:plain
スイーツフォルダ
f:id:Z1000S:20190227173813j:plain
パンフォルダ
f:id:Z1000S:20190227173902j:plain
洋食フォルダ

実行結果

f:id:Z1000S:20190227180741j:plain
実行結果

とりあえず、先頭の定数をいじれば、それなりに使えないかなぁ~



ファイルパスのソートは、一時的に追加したダミーのワークシートに配列から貼り付けて、ワークシート上でソートしてから再度配列に取り込んでます。
データ数が少ないから、セルのデータをフルスキャンしてもいいんだけど、そうしない方向でやってみました。
昔作ったクイックソートのコードを引っ張り出してきても良かったんだけど、いろいろやってみたかったので・・・


サンプルとして使用した素材は、いらすとやよりダウンロードし、使わせていただきました。

CUPS-PDFで大量のページを印刷したら、SSDの空き容量が減ってしまった

うちのノートパソコンには、250GBのSSDが載せてあって、
そこにWindows 10とManjaro Linuxデュアルブートにして使っています。

Manjaro Linuxの/は、112GBしか割り当てしていないので空き容量不足になることは当たり前のこととなっています。

先日、CUPS-PDFを使って300ページ位のデータをPDF化しようとしたら
空き容量が足りずにPDF化出来ませんでした。

原因はそれ以前に他のファイルをPDF化した際に出来たゴミ(?)が残っていたためのようです。
その再現と、対応策を・・・

1.まずPDF作成前の空き容量の確認

f:id:Z1000S:20190217095213p:plain
PDF作成前 空き容量

2.適当なファイルを印刷
今回は、200ページ位のファイルを2つPDF化してみました。

3.ゴミ(?)が出来ていたのは、/var/spool/cups だったので、lsで確認

f:id:Z1000S:20190217095219p:plain
PDF作成後 ゴミファイル作成状況

4.ゴミ(?)ファイルの削除
rmコマンドで、cで始まるファイルと、dで始まるファイルを削除(sudoを使って削除しようとしたけど出来なかったので、rootで削除した)

f:id:Z1000S:20190217095233p:plain
ゴミファイルの削除

5.削除結果の確認

f:id:Z1000S:20190217095242p:plain
ゴミファイル削除結果の確認

6.空き容量の確認

f:id:Z1000S:20190217095247p:plain
空き容量の確認

これで領域確保終了。
普段は、rmコマンド実行の際は、iオプションをつけて確認してるけど、今回は省略。

VBAのDictionaryに配列を格納して、変更してみる

どうせなので、多次元配列(3次元だけど)にしてみた。
テスト用データ
f:id:Z1000S:20180930164204j:plain

その1 配列を格納してみる

Public Sub Dictionaryに配列を追加()

    Dim dicValues   As Dictionary
    Dim lValues(1, 1, 1) As Long
    Dim lKey  As Long
    Dim i   As Long
    Dim j   As Long
    Dim k   As Long

    Set dicValues = New Dictionary

    With ThisWorkbook.Worksheets("Sheet2")
        For i = 2 To 9
            lValues(.Cells(i, 1).Value, .Cells(i, 2).Value, .Cells(i, 3).Value) = .Cells(i, 4).Value
        Next i

        'キー値 0で配列を追加
        dicValues.Add 0, lValues

        Erase lValues

        For i = 10 To 17
            lValues(.Cells(i, 1).Value - 2, .Cells(i, 2).Value, .Cells(i, 3).Value) = .Cells(i, 4).Value
        Next i

        'キー値 1で配列を追加
        dicValues.Add 1, lValues
    End With

    '
    Debug.Print "Dictionary.Itemは配列?:" & IsArray(dicValues.Item(0))
    Debug.Print

    For lKey = 0 To dicValues.Count - 1
        Debug.Print "キー:" & CStr(lKey)

        For i = 0 To UBound(lValues, 1)
            For j = 0 To UBound(lValues, 2)
                For k = 0 To UBound(lValues, 3)
                    Debug.Print i; j; k, dicValues.Item(lKey)(i, j, k)
                Next k
            Next j
        Next i
    Next lKey

End Sub

実行してみる。

call Dictionaryに配列を追加
Dictionary.Itemは配列?:True

キー:0
0 0 0 10000
0 0 1 10001
0 1 0 10010
0 1 1 10011
1 0 0 10100
1 0 1 10101
1 1 0 10110
1 1 1 10111
キー:1
0 0 0 20200
0 0 1 20201
0 1 0 20210
0 1 1 20211
1 0 0 20300
1 0 1 20301
1 1 0 20310
1 1 1 20311

dicValues.Item(lKey) これ自体は配列なんですね。
だから、dicValues.Item(lKey)(i, j, k)という形でアクセス出来るんですね。

その2 追加した配列をまるまる置き換えてみる

Public Sub Dictionaryに追加した配列をまるまる置換()

    Dim dicValues   As Dictionary
    Dim lValues(1, 1, 1) As Long
    Dim lKey    As Long
    Dim i   As Long
    Dim j   As Long
    Dim k   As Long

    Set dicValues = New Dictionary

    With ThisWorkbook.Worksheets("Sheet2")
        For i = 2 To 9
            lValues(.Cells(i, 1).Value, .Cells(i, 2).Value, .Cells(i, 3).Value) = .Cells(i, 4).Value
        Next i

        '同じ配列をキー値 0と1で追加
        dicValues.Add 0, lValues
        dicValues.Add 1, lValues

        For i = 10 To 17
            lValues(.Cells(i, 1).Value - 2, .Cells(i, 2).Value, .Cells(i, 3).Value) = .Cells(i, 4).Value
        Next i

        'キー値 1のItemを値の異なる配列で書き換え
        dicValues.Item(1) = lValues
    End With

    For lKey = 0 To dicValues.Count - 1
        Debug.Print "キー:" & CStr(lKey)

        For i = 0 To UBound(lValues, 1)
            For j = 0 To UBound(lValues, 2)
                For k = 0 To UBound(lValues, 3)
                    Debug.Print i; j; k, dicValues.Item(lKey)(i, j, k)
                Next k
            Next j
        Next i
    Next lKey

End Sub

実行してみる。

call Dictionaryに追加した配列をまるまる置換
キー:0
0 0 0 10000
0 0 1 10001
0 1 0 10010
0 1 1 10011
1 0 0 10100
1 0 1 10101
1 1 0 10110
1 1 1 10111
キー:1
0 0 0 20200
0 0 1 20201
0 1 0 20210
0 1 1 20211
1 0 0 20300
1 0 1 20301
1 1 0 20310
1 1 1 20311

きちんと置き換わっている。

その3 ”追加した配列の要素”だけ変更出来るか?

Public Sub Dictionaryに追加した配列の要素を変更()

    Dim dicValues   As Dictionary
    Dim lValues(1, 1, 1) As Long

    Set dicValues = New Dictionary

    With ThisWorkbook.Worksheets("Sheet2")
        'キー値 0で無変更の配列を追加
        dicValues.Add 0, lValues

        'キー指定して、配列の要素を変更
        dicValues.Item(0)(0, 0, 0) = .Cells(10, 4).Value

        If dicValues.Item(0)(0, 0, 0) <> .Cells(10, 4).Value Then
            Debug.Print "Not equal! orz " & vbCrLf; dicValues.Item(0)(0, 0, 0); .Cells(10, 4).Value
        End If
    End With

End Sub

実行してみる。

call Dictionaryに追加した配列の要素を変更
Not equal! orz
0 20200

値は変わっていない。
dicValues.Item(0)を内容の異なる配列で上書きすることは出来るけれど
その要素dicValues.Item(0)(0, 0, 0)を書き換える事は出来ないみたい。
エラーは出ずに処理は終了するんだけどねぇ・・・
読み取り専用のような感じ。

やっぱり一旦データを変数に取り出して、編集後に再度設定するしかないのかもしれない。

VBAで休日判定処理を使って、Excelワークシートに休日カレンダーを作る

休日判定を作ったので、その応用を2。

Excelのワークシートに休日を指定色にしたカレンダーを作成してみる。
ソースコードへのリンクは下の方に・・・)

更新履歴

2019/6/13
横1列バージョンを追加しました。

仕様みたいなもの

通常(?)の1週間横並び
  • 年指定(1月から12月)
  • 年度指定(4月から翌年3月)

オプション

  • 横1行に表示する月数を可変
  • 書き込み基準位置指定可能
  • 月と月の間のセル数可変(縦、横)
  • 曜日と曜日の間のセル数可変
  • 週と週の間のセル数可変
  • 休日色(背景、文字)可変
  • 日付、曜日、休日名表示
  • 書き込み基準位置指定可能
  • 月、日(日付ではない)、曜日表示
  • 書き込み基準位置指定可能

サンプル画像

(4月29日とか、通常の休日を非休日と設定している部分もあるので、普通の正しい(?)カレンダーとは異なるのでご注意を。)
1月から12月(3×4)
f:id:Z1000S:20180909175227j:plain
1月から12月(4×3)
f:id:Z1000S:20180909175235j:plain
1月から12月(6×2)
f:id:Z1000S:20180909175243j:plain
1月から12月(3×4、日間セルあり)
f:id:Z1000S:20180909175251j:plain
4月から3月(3×4)
f:id:Z1000S:20180909175258j:plain

f:id:Z1000S:20180909175304j:plain

f:id:Z1000S:20190613104721j:plain

事前準備

休日判定処理クラスの休日設定(の確認)

パブリックメソッド

  • createCalendarY(指定年の1月から12月までのカレンダー作成)
  • createCalendarYD(指定年度の4月から3月までのカレンダー作成)
  • createCalendarYMV(指定年月の縦カレンダー作成)
  • createCalendarYMH(指定年月の横カレンダー作成)

ソースコード

▶クリックで展開
注意
既存のワークシートに書き込む場合、以下のコードで確認メッセージなしで、全部クリアされますので・・・

    ws.Range(.Cells(1, 1), .Cells(.Rows.Count, .Columns.Count)).Clear

生成されるワークシート名は、以下の通りです。

TARGET_SHEET_PREFIX & CStr(lYear)

デフォルトのまま使うと
TARGET_SHEET_PREFIX は、"Calendar"
なので、2019年のカレンダーを作ろうとした場合、
Calendar2019
というワークシート名になります。

2021/4/11
都合により、ソースは、こちら に移動しました。
github.com

モジュール先頭の定数を適当にいじって、いろいろ試してみて下さい。

上記とは別に、CCompanyHolidayのソースも必要です。
CCompanyHoliday のソースは、こちらから持っていって下さい。

CCompanyHolidayのソースも、上記リンク にあります。

余談

今回の処理は、Excel限定なので、クラスモジュールの祝日定義のデータを、クラスモジュールからワークシートに移したほうが間違いなく使いやすく(メンテナンスしやすく)なります。
もし、本気で使おうとする(がんばりやさんの)方がいたら、ぜひ挑戦(?)してみて下さい。
祝日情報生成のたぐいのメソッドのインターフェイスを変えずに中身のみ変えれば出来ます。
空腹おやじは、そこまで元気がありませんので・・・

VBAで休日判定処理を使って、指定営業日数後の日付を取得する

休日判定処理を作ったので、その応用を。

「翌営業日の日付が知りたい」とか、そういった類です。
休日判定クラスモジュールを用意して、それとは別に標準モジュールを用意して、以下のコードを貼り付けます。
あとは、getNthWorkingDayに必要なパラメータを渡して呼び出します。
日数は、マイナスをつけることで、過去方向も指定できるようにしてあります。
エラー処理はあまり入れてません。(手抜きです)

2021/4/11
都合により、ソースを、こちら に移動しました。
github.com


実務レベルで、繰り返し使うようなことでもなければ
このサンプルのように、cch_ をモジュールレベルの変数にする必要はないです。
ローカル変数で問題がない場合は、だまってローカル変数にしましょう。
(なぜこうしたかは、気にしないでください)

呼び出しサンプル

Public Sub Test()

    Dim d1 As Date
    Dim d2 As Date
    Dim diff As Long

    d1 = #8/23/2018#

    diff = 9
    Call getNthWorkingDay(d1, diff, d2)
    Debug.Print d1, diff, d2

    diff = -5
    Call getNthWorkingDay(d1, diff, d2)
    Debug.Print d1, diff, d2

End Sub

以下のようなカレンダーに対して実行してみた例

call Test
2018/08/23 9 2018/09/04
2018/08/23 -5 2018/08/09

f:id:Z1000S:20180909171206j:plain

VBAによる「祝日判定処理」を「休日判定処理」に拡張してみた

3ヶ月半ほど前の5月28日に、VBAの祝日判定コードを書いたところ思っていた以上にアクセスされているようで、「以外に需要があるものだ」と少々驚いています。(推定で平日30件たらず?ですけど・・・)

そこで、図に乗った空腹おやじは、前回の祝日判定を拡張し、休日判定出来るようにすることにしました。(「休日でなければ・・・」という判定をすれば、営業日とか稼働日の判定にも使えそうです。)

基本は、前回の祝日判定処理を利用して、祝日定義同様に

  • 月日固定の休日
  • 月週曜日固定の休日
  • 曜日固定の休日

を定義する処理を追加し、祝日判定の時と同様に日付指定でBool値判定。

更に、

  • 特定の祝日、休日を除外できるようにする

といったところでしょうか。

クラスモジュール(CCompanyHoliday)のソースは、長いので下の方に・・・

とりあえず祝日定義は、祝日法が変わらなければ、いじる必要が必要ないと思うので
まずは、休日定義を以下の6個のメソッド内で設定してから使ってみてください。

  • getCompanyHolidayInfoW(曜日固定の会社休日情報生成)
  • getCompanyHolidayInfoMD(月日固定の会社休日情報生成)
  • getCompanyHolidayInfoWN(月週曜日固定の会社休日情報生成)
  • getCompanyHolidayInfoMDExclude(月日固定の会社出勤情報生成)
  • getCompanyHolidayInfoWNExclude(月週曜日固定の会社出勤情報生成)

実行例は、こんな感じ。

Public Sub Test(ByVal lYear As Long)

    Dim cch     As CCompanyHoliday
    Dim dt()    As Date
    Dim i As Long

    Set cch = New CCompanyHoliday

    Call cch.getNationalHolidays(lYear, dt)

    For i = 0 To UBound(dt)
        Debug.Print dt(i), cch.getNationalHolidayName(dt(i))
    Next i

    Set cch = Nothing

End Sub

これをイミディエイトウィンドウで実行してみると

call Test(2018)
2018/01/01 元日
2018/01/02 年始休暇
2018/01/03 年始休暇
2018/01/06 会社休日
2018/01/07 会社休日
2018/01/08 成人の日
2018/01/13 会社休日
2018/01/14 会社休日
2018/01/20 会社休日
2018/01/21 会社休日
2018/01/27 会社休日
2018/01/28 会社休日
2018/02/03 会社休日
2018/02/04 会社休日
2018/02/10 会社休日
2018/02/11 建国記念の日
2018/02/12 振替休日
2018/02/17 会社休日
2018/02/18 会社休日
2018/02/24 会社休日
2018/02/25 会社休日
2018/03/03 会社休日
2018/03/04 会社休日
2018/03/10 会社休日
2018/03/11 会社休日
2018/03/17 会社休日
2018/03/18 会社休日
2018/03/21 春分の日
2018/03/24 会社休日
2018/03/25 会社休日
2018/03/31 会社休日
2018/04/01 会社休日
2018/04/07 会社休日
2018/04/08 会社休日
2018/04/14 会社休日
2018/04/15 会社休日
2018/04/21 会社休日
2018/04/22 会社休日
2018/04/28 会社休日
2018/04/30 振替休日
2018/05/03 憲法記念日
2018/05/04 みどりの日
2018/05/05 こどもの日
2018/05/06 会社休日
2018/05/12 会社休日
2018/05/13 会社休日
2018/05/19 会社休日
2018/05/20 会社休日
2018/05/26 会社休日
2018/05/27 会社休日
2018/06/02 会社休日
2018/06/03 会社休日
2018/06/09 会社休日
2018/06/10 会社休日
2018/06/16 会社休日
2018/06/17 会社休日
2018/06/18 特別休日
2018/06/23 会社休日
2018/06/24 会社休日
2018/06/30 会社休日
2018/07/01 会社休日
2018/07/07 会社休日
2018/07/08 会社休日
2018/07/14 会社休日
2018/07/15 会社休日
2018/07/16 海の日
2018/07/21 会社休日
2018/07/22 会社休日
2018/07/28 会社休日
2018/07/29 会社休日
2018/08/04 会社休日
2018/08/05 会社休日
2018/08/11 山の日
2018/08/12 お盆休暇
2018/08/13 お盆休暇
2018/08/14 お盆休暇
2018/08/15 お盆休暇
2018/08/16 お盆休暇
2018/08/17 お盆休暇
2018/08/18 お盆休暇
2018/08/19 会社休日
2018/08/26 会社休日
2018/09/01 創業記念日
2018/09/02 会社休日
2018/09/08 会社休日
2018/09/09 会社休日
2018/09/15 会社休日
2018/09/16 会社休日
2018/09/17 敬老の日
2018/09/22 会社休日
2018/09/23 秋分の日
2018/09/24 振替休日
2018/09/29 会社休日
2018/09/30 会社休日
2018/10/06 会社休日
2018/10/07 会社休日
2018/10/08 体育の日
2018/10/13 会社休日
2018/10/14 会社休日
2018/10/20 会社休日
2018/10/21 会社休日
2018/10/24 特別休日
2018/10/25 特別休日
2018/10/27 会社休日
2018/10/28 会社休日
2018/11/03 文化の日
2018/11/04 会社休日
2018/11/10 会社休日
2018/11/11 会社休日
2018/11/17 会社休日
2018/11/18 会社休日
2018/11/23 勤労感謝の日
2018/11/24 会社休日
2018/11/25 会社休日
2018/12/01 会社休日
2018/12/02 会社休日
2018/12/08 会社休日
2018/12/09 会社休日
2018/12/15 会社休日
2018/12/16 会社休日
2018/12/22 会社休日
2018/12/23 天皇誕生日
2018/12/24 振替休日
2018/12/29 年末休暇
2018/12/30 年末休暇
2018/12/31 年末休暇


クラスモジュール(CCompanyHoliday)のソースは、▶こちらをクリックで展開します。(注:1055行ありますので・・・ご注意下さい。m(_ _)m)
2021/4/11
都合により、こちら に移動しました。

CCompanyHoliday.cls のみ
https://github.com/Z1000R/determining-and-retrieving-holidays/blob/main/Source/CCompanyHoliday.cls

その他諸々を含めて一式
github.com

お約束

掲載したコードの使用については、特に制限は設けません。MITライセンスとします。
ご自由にお使い下さい。
使用にあたって、私への連絡等は不要です。

ただし、使用した結果、何らかのトラブル、損害、その他諸々の事象が発生しても、私は一切関与しません。
ソースコードを組み込んだ方が責任を取れる範囲内で使って下さい。

バグ、要望、気が付いた事などあれば、コメントしていただければと思います。