cr(カレントリージョン)で、列データの種類ごとに小計を取る。

f:id:bimori466:20210504162812p:plain

cr(カレントリージョン)を条件分岐して取得する。

crは条件分岐して取得することができます。今回は、預金者区分1,2,3、の3種類のcrを作ってそれぞれの小計を出します。

1 閲覧対象者

cr(カレントリージョン)を条件分岐で取得する方法を、マスターしたい人。

2 得られる効果

条件設定して得られたRangeを簡単に操作できます。

3 演習問題

以下のような表があります。
f:id:bimori466:20210505050630p:plain


演習問題
・この表からA列の預金者区分1,2、3ごとに小計だしてください。


ポイントは、3つのRangeを宣言してそれぞれに範囲を取って合計を出すことです。
では、次の章の回答コードを見ていきましょう。

4 コードの解説

回答コード

Sub cr_Subtotal()

    Dim cr As Range: Set cr = Range("A1").CurrentRegion
    Dim i As Long
    Dim targetRange1 As Range, targetRange2 As Range, targetRange3 As Range
    Dim taget1_Subtotal, taget2_Subtotal, taget3_Subtotal
    
    For i = 2 To cr.Rows.Count
        '預金者区分1
        If cr.Cells(i, 1) = 1 Then
            If targetRange1 Is Nothing Then
                Set targetRange1 = cr.Rows(i)
            Else
                Set targetRange1 = Union(targetRange1, cr.Rows(i))
            End If
            
        '預金者区分2
        ElseIf cr.Cells(i, 1) = 2 Then
            If targetRange2 Is Nothing Then
                Set targetRange2 = cr.Rows(i)
            
            Else
                Set targetRange2 = Union(targetRange2, cr.Rows(i))
            End If
        
        '預金者区分3
        ElseIf cr.Cells(i, 1) = 3 Then
            If targetRange3 Is Nothing Then
                Set targetRange3 = cr.Rows(i)
            
            Else
                Set targetRange3 = Union(targetRange3, cr.Rows(i))
            End If
        End If
    Next
    
    '小計を取得する。
    If Not targetRange1 Is Nothing Then taget1_Subtotal = WorksheetFunction.Sum(targetRange1.Columns(3))
    If Not targetRange2 Is Nothing Then taget2_Subtotal = WorksheetFunction.Sum(targetRange2.Columns(3))
    If Not targetRange3 Is Nothing Then taget3_Subtotal = WorksheetFunction.Sum(targetRange3.Columns(3))
    
    Debug.Print taget1_Subtotal
    Debug.Print taget2_Subtotal
    Debug.Print taget3_Subtotal
        
End Sub


まず、区分が1、2、3と3つ存在するのでtargetRangeを3つ用意します(targetRange1~targetRange3)。
cr(カレントリージョン)のA列が1の場合は、targetRange1に範囲をSetします。
cr(カレントリージョン)のA列が2の場合は、targetRange2に範囲をSetします。
cr(カレントリージョン)のA列が3の場合は、targetRange3に範囲をSetします。
targetRange1 がNothingでない場合、targetRange1の預金額を合計します(Columns(3)が預金額欄です)。
targetRange2がNothingでない場合、targetRange2の預金額を合計します(Columns(3)が預金額欄です)。
targetRange2がNothingでない場合、targetRange3の預金額を合計します(Columns(3)が預金額欄です)。
Debug.Printでそれぞれ値を出します。


Debug.Printの出力結果
f:id:bimori466:20210505054406p:plain


期待通りの小計が取得できていることが確認できます。

5 とある信用金庫さんへの悩みを解決する

もう一度、処理対象の表を確認します。
f:id:bimori466:20210505053327p:plain


次の条件でcrから範囲を取得します。
1 預金金額は1以上
2 預金額が3000円の場合は除く


ではコードに落とし込んでいきましょう!

Sub cr_Subtotal2()

    Dim cr As Range: Set cr = Range("A1").CurrentRegion
    Dim i As Long, myRnge As Range
    Dim targetRange1 As Range
    Dim taget1_Subtotal
    Dim rangeCount As Long
    
    For i = 2 To cr.Rows.Count
        '預金額が1以上
        If cr.Cells(i, 3) > 1 Then
            '預金額が3000円で無い場合
            If Not cr.Cells(i, 3) = 3000 Then
                If targetRange1 Is Nothing Then
                    Set targetRange1 = cr.Rows(i)
                Else
                    Set targetRange1 = Union(targetRange1, cr.Rows(i))
                End If
            End If
        End If
    Next
    
    '3000円の列以外が選択できていることが確認できる。
    targetRange1.Select
    
    '小計を取得する。
    If Not targetRange1 Is Nothing Then: taget1_Subtotal = 0
        For Each myRnge In targetRange1
            rangeCount = rangeCount + 1
            If rangeCount = 3 Then
                taget1_Subtotal = taget1_Subtotal + myRnge.Value
                rangeCount = 0
            End If
        Next
    
    Debug.Print taget1_Subtotal

End Sub


IF文で預金額が1以上かつ、3000円以上の場合、targetRange1にSetします。
targetRange1.Selectで、3000円以外のセルが選択できていることが確認できます。
小計は、ごめんなさいSumで簡単に取れなかったので、苦肉の策で「For each in next」でループして、変数rangeCount =3(預金額のデータの時)に変数taget1_Subtotal に預金額を足して小計を出しています。もっとスマートな方法は考えておきますm(_ _"m)。


Debug.Printの結果
f:id:bimori466:20210505062852p:plain

きちんと3000円以外の小計が取れています。ちなみに、変数taget1_Subtotal はVariant型にしてます。Long型でもオーバーフローするとのことだったので。


ちなみに、targetRange1.Selectをした時の画像↓↓
f:id:bimori466:20210505061933p:plain


預金額が3000円以上の行が選択されています。

改良版

改良コード↓↓

Sub cr_Subtotal2_Ver2()

    Dim cr As Range: Set cr = Range("A1").CurrentRegion
    Dim i As Long, myRnge As Range
    Dim targetRange1 As Range, targetCountRange1 As Range
    Dim taget1_Subtotal
    Dim rangeCount As Long
    
    For i = 2 To cr.Rows.Count
        '預金額が1以上
        If cr.Cells(i, 3) > 1 Then
            '預金額が3000円で無い場合
            If Not cr.Cells(i, 3) = 3000 Then
                If targetRange1 Is Nothing Then
                    Set targetRange1 = cr.Rows(i)
                    Set targetCountRange1 = cr.Cells(i, 3)
                Else
                    Set targetRange1 = Union(targetRange1, cr.Rows(i))
                    Set targetCountRange1 = Union(targetCountRange1, cr.Cells(i, 3))
                End If
            End If
        End If
    Next
    
    '3000円の行以外の列Cが選択できていることが確認できる。
    targetCountRange1.Select
    
    '条件にあった預金額の小計を取る。
    If Not targetRange1 Is Nothing Then taget1_Subtotal = WorksheetFunction.Sum(targetCountRange1)
    
    Debug.Print taget1_Subtotal

End Sub


変数targetCountRange1 を追加しました。これは、預金額の部分のみの範囲を取得します。
よって、変数taget1_Subtotal にSum関数で一発で小計が取得できます。
少しだけスマートになりました!

6 感想

いや~、複数のcrを選択した場合、cr.Rows.Count=2になってしまうことに気づきました(;^ω^)
行13まで選んでくれると思ったら、途切れたセルの範囲は取得してくれませんでした(´;ω;`)
とりあえず、やっつけで「For each in next」作ってみました。
とある信用金庫さん、参考にならなかったらすんませんm(_ _"m)
crの極意をもっと勉強します。


ではでは、この辺で(^^)/~~~

cr(カレントリージョン)で、2つおきの行を削除する。

f:id:bimori466:20210504162812p:plain

cr(カレントリージョン)の普及活動!

cr(カレントリージョン)って何?と思われるでしょう。一言でいうと、セルの範囲操作が容易になります。
この記法は「ほえDX塾」で教わったものです。ブログへの記載OKということなので、この便利さを伝えたいなと思います。
気が向いたら、シリーズ化します。

1 閲覧対象者

crの記法を学んで、セルの範囲操作の幅を広めたい人。

2 得られる効果

セルの範囲(Range)を簡単に操作することができる。

3 演習問題

以下のような表があります。

f:id:bimori466:20210504154949p:plain

演習問題
・この表から2つおきの行を選択してください。


正直、この問いへの答えが出せませんでした。For Nextでループさせても、Selectしたままにできんな~(;^ω^)とお手上げでした。
そんなときcr(カレントリージョン)がすごく便利なのです。久々にコードを見て感動しました。


ちなみにこの問いに対する正解は、以下の画像の状態です。
f:id:bimori466:20210504155626p:plain


2,4,6、~12の行を選択します。ここまでみなさんは回答のコードを作れますか?
ではでは、回答のコードは次の章です。

4 コードの解説

Sub cr_Union()

    Dim cr As Range: Set cr = Range("A1").CurrentRegion
    Dim i As Long
    Dim myRange As Range
    
    For i = 2 To cr.Rows.Count Step 2
        If i = 2 Then
            If myRange Is Nothing Then
                Set myRange = cr.Rows(i)
            End If
            
        Else
            Set myRange = Union(myRange, cr.Rows(i))
        End If
    Next
    
    myRange.Select
        
End Sub


変数crにRange("A1").CurrentRegionの範囲をセットします。
初期値2で「For next Step 2」でループ処理します。
変数myRangeにcrの行を格納していきます。ポイントは、myRangeの初期状態は「Nothing」となっているので、1回目のSetで範囲を設定するときはNothingかどうかの判定が必要です。
2回目以降は、myRangeに「Union(myRange, cr.Rows(i))」で追加格納していきます。
このようにして、2行おきのデータを格納していきます。
そして、最後の「myRange.Select」で選択します。

これが問題の回答コードとなります。

5 2行おきのデータを削除する

ここからは、crを応用した処理です。

crからmyRangeでセルを選択できました。次に、myRangeを削除してみましょう。削除するには、以下のコードです。

Sub cr_Union()

    Dim cr As Range: Set cr = Range("A1").CurrentRegion
    Dim i As Long
    Dim myRange As Range
    
    
    For i = 2 To cr.Rows.Count Step 2
        If i = 2 Then
            If myRange Is Nothing Then
                Set myRange = cr.Rows(i)
            End If
            
        Else
            Set myRange = Union(myRange, cr.Rows(i))
        End If
    Next
    
    myRange.Select
    myRange.Delete
        
End Sub


「myRange.Delete」を追加するだけです。


処理した状態が以下の画像です。
f:id:bimori466:20210504161923p:plain


myRangeの範囲のデータが削除されます。
普通、2行おきのデータを削除するというと「For next Step -1」でDeleteしていくのではないでしょうか?
しかし、crを使えば指定の範囲を分かりやすいイメージで削除できます。

6 感想

いかがだったでしょうか?セルの範囲選択といっても奥が深いと思いました。cr(カレントリージョン)を使うことで指定の範囲への操作が容易となります。
次回は、複数のmyRangeを取得して並び替える処理について記事を書こうと思います。


ではでは、この辺で(^^)/~~~

ウェブページを表示するコントロールWebBrowserの表示を方法。表示のさせ方。

f:id:bimori466:20210403052656p:plain

ユーザフォーム上でGoogleを検索ができる

上の写真の様に、ユーザフォーム上にGoogleを表示できます。ユーザフォームの中で検索もできます。
いや、Chrome開けよ!って話なんですが。なんか面白いので記事にしてみました。

1 閲覧対象者

ユーザフォーム上で、Chromeを開いて検索したい方。

2 得られる効果

Chromoeを直に開かなくてよい。

3 WebBrowserをユーザフォームコントロールに表示する

以下の画面の蛍光線部が、WebBrowserコントロールです。しかし、デフォルトでは表示されません。
まずは表示方法から、解説します。

f:id:bimori466:20210403054052p:plain

1 ツールボックス_コントロールの確認

以下の画像の通り、WebBrowserコントロールはありません。では、追加していきましょう!

f:id:bimori466:20210403054410p:plain

2 WebBrowserコントロールの追加

以下の画像の通り、ツールボックス_コントロールを右クリックします。すると、その他のコントロールと出るので、クリックします。

f:id:bimori466:20210403054724p:plain


すると、以下のようなコントロールの追加画面が出てきます。ここで、「Microsoft Web Browser」にチェックを入れ追加します。

f:id:bimori466:20210403055100p:plain


こうすることで、ツールボックスの中に「WebBrowserコントロール」を選択できるようになります。

f:id:bimori466:20210403054052p:plain

4 WebBrowserコントロールを使ってみよう!

では、実際にWebBrowserコントロールを配置してみましょう!
WebBrowserコントロールを配置すると、以下の画像の様に真っ暗な画面になります。少々不安になりますが、これでOK!

f:id:bimori466:20210403055854p:plain


では、UserForm_Initialize処理時にWebBrowserコントロールに「Googleを表示」するように設定しましょう!

5 WebBrowserコントロールGoogleを表示する

コードは超絶簡単です。UserForm_Initializeの中に以下のコードを書き込みます。

Private Sub UserForm_Initialize()

    WebBrowser1.Navigate "https://www.google.co.jp/"

End Sub


こんだけです。では、標準モジュールにUserForm1.Showの処理を追加して実行すると以下の通り。

f:id:bimori466:20210403060454p:plain


何ということでしょう。ユーザーフォーム上にGoogleが表示されました。しかも、普通にこの中で検索できます。
以下の画像の通り、入力します(宣伝w)。

f:id:bimori466:20210403060826p:plain


Enterで検索すると、以下の画像の通り。何と言いうことでしょう、吾輩のブログがでてきました(宣伝w)。

f:id:bimori466:20210403061008p:plain


ちなみに、戻るボタンが表示されないのでその辺はショートカットキー「Alt+←」で検索画面に戻りましょう!

6 まとめ

いかがだったでしょうか。ユーザーフォーム上にWebブラウザを表示できるという感動はありつつも、Chrome開けばよくね?という正論の狭間にある心境です(;^ω^)。

しかし、IEコントロールで中の動きを制御できるみたいなので、Webスクレイピングの幅が広がったりするのか?。そんな期待感もあります。

この手の情報は、バスっとネットに転がってないんですよね。なんかいい記事みつけたら随時更新していきます。


ではでは、この辺で(^^)/~~~

全てのサブフォルダのファイル名を変更する。

全てのサブフォルダのファイル名を変更する

設計書のドキュメントファイルを自動生成する野良マクロと遭遇しました。怒りを覚えたが、お仕事なので解読しましたw。
その処理の中で、ドキュメント生成ができたら普通のファイル名、出来なければファイル名の頭に”×”が付きます。
10ファイルくらいならいいのですが、100ファイルを超えるとやってられないですよね。
なので、すべてのサブフォルダのエクセルファイル名を変更するコードを考えました。

1 自動生成されたファイルの例

以下の画像のようなファイル構成があります。
f:id:bimori466:20210320233921p:plain


以下の画像のように、ファイルA、ファイルBの中に先頭に×が付いているファイルと、付いていないファイルがあります。
f:id:bimori466:20210320232346p:plain


×が付いているファイルを、編集後に×を取ります。×がついたファイルが数百ファイルも有ったらやってられないですよね。
では、ピョログラミングでハムハムしましょう!

2 実際のコード

Sub サブフォルダのファイル名を更新する()

    Dim fso As Object: Set fso = CreateObject("scripting.filesystemobject")
    Dim myPath As String: myPath = ThisWorkbook.Path
    
    Dim targetPath As String
    Dim oldName As String
    Dim newName As String
    
    Dim myFolder As Variant
    For Each myFolder In fso.GetFolder(myPath).SubFolders
        
        targetPath = ThisWorkbook.Path & "\" & myFolder.Name
        
        Dim myFile As Variant
        For Each myFile In fso.GetFolder(targetPath).Files
            
            oldName = myFile.Name
            
            'ファイル名の頭に×があれば、MIDで×を除いたファイル名にする。
            If Mid(oldName, 1, 1) = "×" Then
                newName = Mid(oldName, 2)
                
                oldName = targetPath & "\" & oldName
                newName = targetPath & "\" & newName
                
                'ファイル名の変更(Nameステートメント)
                Name oldName As newName
            End If
        Next
    Next

End Sub


FSOと、Nameステートメントを使います!

3 処理結果

下の画面の通り、ファイル名から×が取れております。
f:id:bimori466:20210320233435p:plain


ファイル名を変更する「Name」ステートメント、VBA9年目にして初めて知りました。まだまだ奥が深いですVBA。


ではでは、この辺で(^^)/~~~

サブフォルダーのファイルを取得するVBA

f:id:bimori466:20210313010901p:plain

サブフォルダーのファイルまで取得するVBA

仕事が超絶楽になるはずだよ!

1 作成の経緯

ドキュメントの一括作成を迫られたのでw

2 コードを記載

以下のようにファイルA、B、C、Dのフォルダがあります。
f:id:bimori466:20210313004402p:plain


以下のようにフォルダの中にエクセルファイルが入っています。
f:id:bimori466:20210313004712p:plain

サブフォルダーを取得する実際のコード

Sub サブフォルダのファイルまで取得する()

    Dim fso As Object: Set fso = CreateObject("scripting.filesystemobject")
    
    Dim varTmp As Variant
    Dim myFolser As String
    
    
    Dim targetPath As String
    Dim targetSubPath As String
    
    Dim files As Variant
    Dim file As Variant
    Dim myFile As Variant
    
    targetPath = ThisWorkbook.Path
    
    For Each varTmp In fso.GetFolder(targetPath).SubFolders
    
        'Debug.Print varTmp.Name
            
        targetSubPath = targetPath & "\" & varTmp.Name
        
        Set files = fso.GetFolder(targetSubPath)
        Set file = files.files
        
        For Each myFile In file
            Debug.Print myFile.Name
        Next
    Next
    
    Set fso = Nothing

End Sub

処理結果

f:id:bimori466:20210313005822p:plain

3 感想

fsoを作って、サブフォルダを取得してイミディエイトウィンドウに出力しているだけです。
For Each myFile In fileの処理の中で、すべてのサブフォルダのファイルを処理できます!
いつでも、どこかで使えそう!


備忘録でした~。(^^)/~~~

ドキュメント自動生成ひな形

作成途中

Option Explicit

Sub すべてのファイルに値を代入()

'FSOを宣言
Dim fso_lord As Object: Set fso_lord = CreateObject("scripting.filesystemobject")
Dim wbPath As Variant
Dim myfiles As Variant
Dim file As Variant

Dim Input_wb As Workbook
Dim Input_LastLline As Long
Dim Output_Path As Variant


Dim mySh As Worksheet

Dim Item1 As String
Dim Filename As String


'pathの設定
wbPath = ThisWorkbook.Path & "\INPUTファイル\"

Set myfiles = fso_lord.getfolder(wbPath).Files
    
For Each file In myfiles
    If Not file.Name Like "~$*" Or file.Name Like ".xlsx" Then
        Call OpenBooks_String(wbPath & file.Name)
        Set Input_wb = ActiveWorkbook
        
        
        Workbooks.Add
        Filename = "成果物1"
        ActiveWorkbook.SaveAs Filename:=ThisWorkbook.Path & "\成果物\" & Filename
        Output_Path = ActiveWorkbook.Name
        
        
        'ブック間のデータのやり取り!
        Workbooks(file.Name).ActiveSheet.Range("A1").Copy Workbooks(Output_Path).Sheets(1).Range("A1")
        
        
'        Workbooks(file.Name).Activate
'        Sheets("INPUT_ITEM").Range("A1").Copy
'
'        Workbooks(Output_Path).Activate
'        Range("A1").PasteSpecial Paste:=xlPasteValues
'
        
        
        
        
        '対象のSheetを探す処理
        For Each mySh In Input_wb.Worksheets
            
            '特定のsheetを処理する
            If mySh.Name = "INPUT_ITEM" Then
                
                Item1 = mySh.Range("A2")
                
                MsgBox mySh.Name
            
            End If
            
        
        Next
        
    
        
        '転記する処理
        Workbooks.Add
        
        
        Call CloseBooks_Sring(file.Name)
    End If
Next


End Sub


Sub OpenBooks_String(ByVal mypath As String)
    
Workbooks.Open mypath
'Range("A1").Value = "自動で開きました。"

End Sub


Sub CloseBooks_Sring(ByVal myName As String)
    
Dim wb As Workbook
Set wb = Workbooks(myName)

wb.Close (True)

End Sub

ファイルの結合の項目チェックをするVBA!

ファイルの項目がInputファイル、outputファイルに存在するかを調べる

f:id:bimori466:20210228082517p:plain

INPUTファイルから、OUTPUTファイルを作りますよね。それなのに、OUTPUTファイルの項目に、INPUTファイルの項目が無いという現実(´;ω;`)。
こんな事態を打破すべく、ExcelVBAでチェックツールを作りました。

1 閲覧対象者

INPUTファイルとOUTPUTファイルの項目名が違うとお怒りの方w

2 得られる効果

OUTPUTファイルにINPUTファイルの項目が無いものを特定できる!

3 設計

1 以下の写真の通り、2つのINPUTファイルから1つのUnionファイル(OUTPUTファイル)を作成します。
f:id:bimori466:20210228080416p:plain


2 以下の写真の通り、マクロ「結合比較を実施します」
f:id:bimori466:20210228080634p:plain


3 以下の写真の通り、列F「判定」にINPUTファイルに含まれるものは「項目有」と表示される。空白のものが、INPUTファイルに項目が無いものとなる。
f:id:bimori466:20210228080758p:plain

4 コードの解説

<マクロ結合比較のコード>

Sub 結合比較()

    Dim ws As Worksheet: Set ws = Worksheets("結合比較")
    
    Dim input1 As Long: input1 = ws.Cells(Rows.Count, 1).End(xlUp).Row
    Dim input2 As Long: input2 = ws.Cells(Rows.Count, 3).End(xlUp).Row
    Dim Union_output As Long: Union_output = ws.Cells(Rows.Count, 5).End(xlUp).Row
    
    Dim serchItem As String
    Dim compItem As String
    Dim endFlg As Boolean
    
    
    'inputファイル1を探す
    Dim k_serchItem As Long
    For k_serchItem = 2 To Union_output
        endFlg = False
        serchItem = ws.Cells(k_serchItem, 5)
        
        Dim k_input1 As Long
        For k_input1 = 2 To input1
            compItem = ws.Cells(k_input1, 1)
            
            If serchItem = compItem Then
                ws.Cells(k_serchItem, 6) = "項目有"
                endFlg = True
                Exit For
            End If
            
        Next
        
        
        'inputファイル1に無い場合、Input2を探す
        If endFlg = False Then
            Dim k_input2 As Long
            For k_input2 = 2 To input2
                compItem = ws.Cells(k_input2, 3)
                
                If serchItem = compItem Then
                    ws.Cells(k_serchItem, 6) = "項目有"
                    endFlg = True
                    Exit For
                End If
            Next
        End If
    Next
    
End Sub


単純なコードです。
For~NEXTでファイル1を検索し、その次にファイル2を検索する。
項目があれば、列Fに”項目有”と表示して、endFlgをTrueにする。この処理を繰り返す。

5 感想

この設計の場合、2つのファイルから1つのOUTPUTファイルを作る場合に限定されてしまします(;^ω^)。
3つのファイルから、2つのファイルを作るなどには対応していません。
そこらへんは改良が必要ですが、取り急ぎ業務改善に必要なコードを作ってみました。
私も別のパータンが出てきたら、改良を加えるつもりです。


ではでは、この辺で(^^)/~~~