ラベル #VBA の投稿を表示しています。 すべての投稿を表示
ラベル #VBA の投稿を表示しています。 すべての投稿を表示

2023年3月2日木曜日

【社内DX案件紹介】値の入っているシートのみ印刷する

 ■社内DXの依頼内容

ブックの中でB1セル以下に値があるシートのみを印刷したい


■社内DXの条件

・1シート目は印刷対象外としたい

・2シート目以降でB1セル以降に値があるシートを印刷したい

・印刷するシートはマクロが入っているブック内にある


■諸元

・2シート目から全シートを周回する

・B2セル以降に値があれば配列にシート名を格納する

・シート名が入った配列を対象として印刷プレビューする


■作成方法

1.2シート目からデータのあるファイルを準備する。

2シート目4シート目6シート目に値があるブック

2.実際にマクロを書いていく

Sub Sample()

Dim st() As String  '/--シート名を格納する配列--/'
Dim i As Integer    '/--シート周回カウンタ--/'
Dim m As Integer    '/--最大シート数--/'
Dim c As Integer    '/--配列用カウンタ--/'
Dim y As Long       '/--行数を格納--/'

'/--全シート数を入れる--/'
m = Worksheets.Count

'/--配列は0スタートなので+1したときに0になるようカウンタは-1からスタート--/'
c = -1
For i = 2 To m
    y = Sheets(i).Cells(Rows.Count, 2).End(xlUp).Row
    If y > 1 Then
        c = c + 1
        ReDim Preserve st(c)
        '/--シート名を配列に格納する--/'
        st(c) = Sheets(i).Name
    End If
Next i

'/--配列に格納したシート名のみを印刷プレビューする--/'
Sheets(st).PrintPreview


End Sub


3.マクロ処理結果

2シート目、4シート目、6シート目の印刷プレビュー画面が表示されます。

印刷プレビュー


■マクロ解説

1.複数シートを印刷する(今回は印刷プレビュー)

Sheets(配列名).PrintPreview


st(0)="値あり1"

st(1)="値あり2"

st(2)="値あり3"

という配列があったととして、

Sheets(st).PrintPreview

とすると、中身は

Sheets(Array("値あり1","値あり2","値あり3")).PrintPreview

と同義となるので、シート「値あり1」、シート「値あり2」、シート「値あり3」が選択された状態で印刷プレビューがかかる


↓よろしければクリックをお願いします!



TOPページへ戻る


■社内DX案件紹介

【社内DX案件紹介】アンケートの集計-1-

【社内DX案件紹介】アンケートの集計-2-

【社内DX案件紹介】架電内容ごとの情報振り分け-1-

【社内DX案件紹介】架電内容ごとの情報振り分け-2-

【社内DX案件紹介】2つのファイルの内容を比較する

【社内DX案件紹介】封入物の重さによって印刷会社を変える

【社内DX案件紹介】データの期間によってレコードを分割しファイル出力する


■社内DXの進め方

【社内DXの進め方】ブログの目的(会社が求めるDX)

【社内DXの進め方】社内DXの推進について

【社内DXの進め方】社内DXは具体的に何をすればよいのか?

【社内DXの進め方】なぜ今Excelか?

2023年1月25日水曜日

【マクロVBA】VBA_TIPS-03 マクロの可読性

社内ツールの問題点 

よく社内DXや社内ツール、社内マクロ等で問題となる以下の事象があります。

・前任のSEが作ったツールのドキュメントが無い
・前任が作ったツールを改修したいが解読が難しい


社内ツール作成後、きちんと仕様書を残してくれれば後任は助かるのですが、たいていの場合作って「はい!終わり!」がほとんどだと思います。

また社内SEが社員ならまだ人事異動しても社内に残っているので聞ける可能性もありますが、社内SEが派遣社員だった場合、契約満了後は聞くことすらできなくなります。
実際、過去に私のいた部署で大規模なシステムを構築した際に、ドキュメントが無いままSEがいなくなり、そのシステムを改修をするのに3名の派遣SEを雇いましたが結局解読できずじまいだった。
そんなことも往々にしてあるようです。

作った本人は「なんでSEなのに読み解けないの?」だと思いますし、解読する側は「なんでこんなわかりづらい書き方するの?」だと思います。

それぞれのSEの技術の差があれど、仕様書等のドキュメントを残さないのであれば可読性の高い書き方(誰でも読めばわかる書き方)をすべきだと思います。


なぜ可読性が低いのか?

ネットに載っているコードのコピペ

プログラムを書く際に、ホームページ等のコードを参考にすることも多いかと思います。

ただプログラムを書く人はたいてい書き方にクセが出てくるので、同じようなコードのようでも変数の使い方や関数の使い方が微妙に違ったりします。
ネットのコピペを行うと、いろいろな人のクセが入り混じったコードになるので解読が難しくなります。

例えば以下のようなコードがあったとして、メッセージボックスに表示されるのはどれだかパッと出ますか?

Sub TEST()

Range("F5").Value = "鈴木"
Range("V5").Value = "佐藤"
Range("M5").Value = "田中"

MsgBox Cells(5, 13).Value

End Sub








正解は

正解は田中


きちんと見ればわかるのですが、RangeとCellsが混在しているだけでも少し混乱しませんか?
このようにネットのコピペばかり使うと統一感が無くなってしまうので、可読性は低くなります。


ドキュメント作らないくせに効率重視

プログラムに慣れてくるとどうしても効率を優先してしまう場合があります。

例えばこんなデータがあったとして

会員情報

以下のように1行ずつデータを処理しある要素をメッセージボックスに表示させるとします。

Sub TEST2()

Dim Arry() As String
Dim y As Long
Dim x As Integer

ReDim Arry(8)
For y = 2 To 2
    For x = 1 To 9
        Arry(x) = Cells(y, x).Value
    Next x
    MsgBox Arry(5)
Next i

End Sub
このとき表示されるのは”2023”ですが、この2023は対象期間(前)?それとも対象期間(後)?どちらでしょう。

こんな感じでドキュメントを残してくれればすぐわかるのですが、

配列名インデックス内容
Arry()0会員番号1
1会員番号2
2会員番号3
3会員番号4
4会員氏名
5対象期間(前)_年
6対象期間(前)_月
7対象期間(後)_年
8対象期間(後)_月

ドキュメントが無い場合はやはり解読に時間がかかります。

このようにドキュメント作らないくせに効率を求めたコードを書くと、後任がすごく困ります。


可読性を高くするには

変数の仕様書だけでもあると、SEは解読にさほどの時間がかかりませんが、それが無い(もしくは作らない)のであれば、これからのSEはたとえクソコードと言われようとも初心者でもわかるコードの書き方をすべきだと思います。

変数の統一

できるだけ変数はルール化しておくと理解が早くなります。

たとえば

Integer型ならintHogehoge
String型ならstrHogehoge

のように変数名の前に型の略称を入れておくと変数を見ただけで「これは文字列型」と理解が早くなります。

また、周回用のカウンタではiやcがよく用いられますが、Excelマクロで縦横周回させるようであれば縦y横xと誰もが学生時代に習ったxyを使用するとより理解度が増します。


たとえ行数が増えても、簡単な書き方を心がける

昔のPCはCPUやメモリが貧弱だったので、より効率よくプログラムを書く必要がありましたが、今の時代オフィス業務をやるにしては高性能なCPU、オフィス業務では絶対使いきれないメモリ容量と正直PCの性能が上がりすぎてあまり効率的に書く必要性が無くなってきたと思います。

例えば↑で書いた

Sub TEST2()

Dim Arry() As String
Dim y As Long
Dim x As Integer

ReDim Arry(8)
For y = 2 To 2
    For x = 1 To 9
        Arry(x) = Cells(y, x).Value
    Next x
    MsgBox Arry(5)
Next i

End Sub

ですが、

配列名インデックス内容
Arry()0会員番号1
1会員番号2
2会員番号3
3会員番号4
4会員氏名
5対象期間(前)_年
6対象期間(前)_月
7対象期間(後)_年
8対象期間(後)_月

があれば解読は簡単ですが無い場合はやはり解読に時間がかかります。

しかし以下のように記載すると

Sub TEST3()

Dim y As Long
Dim str会員番号1 As String
Dim str会員番号2 As String
Dim str会員番号3 As String
Dim str会員番号4 As String
Dim str会員氏名 As String
Dim str対象期間_前_年 As String
Dim str対象期間_前_月 As String
Dim str対象期間_後_年 As String
Dim str対象期間_後_月 As String

For y = 2 To 2
    str会員番号1 = Cells(y, 1).Value
    str会員番号2 = Cells(y, 2).Value
    str会員番号3 = Cells(y, 3).Value
    str会員番号4 = Cells(y, 4).Value
    str会員氏名 = Cells(y, 5).Value
    str対象期間_前_年 = Cells(y, 6).Value
    str対象期間_前_月 = Cells(y, 7).Value
    str対象期間_後_年 = Cells(y, 8).Value
    str対象期間_後_月 = Cells(y, 9).Value
    MsgBox str対象期間_前_年
Next i

End Sub

変数の内容も、メッセージボックスに表示される内容も一目瞭然です。


仕様書がきちんとあれば正直効率よくコードを書いてドキュメントを残す。これが一番きれいだと思いますが、社内SEの大きな利点は口頭で

社員「こういうの作ってほしい」
SE「できましたー」

だと思うので、仕様書を必ず作る必要はないと思いますが、ならばぜひコードの書き方を工夫するのも良いと思います。


↓よろしければクリックをお願いします!

TOPページに戻る


■関連ページ

【マクロVBA】VBA_TIPS-02 Select文とIf文


2023年1月21日土曜日

【社内DX案件紹介】データの期間によってレコードを分割しファイル出力する

 ■社内DXの依頼内容

・2つのインプットファイルがあり、その中の複数シートのデータを、1つのアウトプットファイル、1シートに集約しXLSファイルとして出力したい

・処理漏れや誤処理厳禁のため、処理後に処理漏れ確認および誤処理検知できるような仕様としたい

A社B社2つのファイルを集約し、出力する


■社内DXの条件

1.2つのインプットファイル(A社ファイル,B社ファイル)は、2シート目から順に転記

2.インプットファイル、“対象期間(前)”と“対象期間(後)”の月数が、12か月以内のものは、そのまま転記し、13か月以上のものは"1月~12月”の表示形式で最大12か月の期間で行を分ける。(1行の内、期間は年を跨がない)

(例)「対象期間(前):2021年5月」「対象期間(後):2023年3月」の場合

対象期間(前)対象期間(後)
1行目20215202112
2行目20221202212
3行目2023120233

3.ファイルパス、ファイル数、ファイル名は固定(拡張子は.xlsx or .xls)。

4.シート数、シート名は変動有り(データ記載は2シート目~は固定)


■諸元

・インプットファイルを開く

・2シート目からの情報を取得する

・対象期間(前)と対象期間(後)の期間が12か月以内かどうか判断し、転記する
 なお13か月以上の場合は年単位で分割し転記する

・転記は検証用シート「処理結果」とアウトプット用シート「output」にそれぞれ転記することとし、「処理結果」で処理漏れがないか確認できるようにする

・アウトプット用シート「output」を新規ブックにコピーし.xls形式にて保存する


■作成方法

1.2シート目からデータのある2つのファイルを準備する。

  なおデータの配置は以下とします。
  ・A~D列:番号
  ・E列   :氏名
  ・F列   :対象期間(前)の年
  ・G列   :対象期間(前)の月
  ・H列   :対象期間(後)の年
  ・I列    :対象期間(後)の月

A社ファイル

B社ファイル

2.実際にマクロを書いていく

Sub Main()

Dim strFP   As String       '/--フォルダパス--/'
Dim strFN   As String       '/--ファイル名--/'
Dim mWB     As Workbook     '/--マクロのワークブック--/'
Dim iWB     As Workbook     '/--インプットファイルのワークブック--/'
Dim iWS     As Worksheet    '/--インプットファイルのワークシート--/'


Dim cWS As Integer          '/--シート数格納--/'
Dim s As Integer            '/--シート数カウンタ--/'
Dim n As Integer            '/--年周回カウンタ--/'
Dim y As Long               '/--インプットファイル 行カウンタ--/'
Dim yI As Long              '/--インプットファイル 行数格納--/'
Dim yO As Long              '/--アウトプットファイル 行数格納--/'
Dim yR As Long              '/--処理結果 行数格納--/'

Dim strNo1 As String        '/--番号1Block目--/'
Dim strNo2 As String        '/--番号2Block目--/'
Dim strNo3 As String        '/--番号3Block目--/'
Dim strNo4 As String        '/--番号4Block目--/'
Dim strName As String       '/--氏名--/'
Dim lngFromY As String      '/--対象期間(前)(年)--/'
Dim intFromM As String      '/--対象期間(前)(月)--/'
Dim dateFrom As Date        '/--対象期間(前)(年月)--/'
Dim lngToY As String        '/--対象期間(後)(年)--/'
Dim intToM As String        '/--対象期間(後)(月)--/'
Dim dateTo As Date          '/--対象期間(後)(年月)--/'
Dim lngDiffY As Long        '/--対象期間(年)--/'
Dim lngDiffM As Long        '/--対象期間(月)--/'

Set mWB = ActiveWorkbook
strFP = mWB.Sheets("メイン").Cells(2, 2).Value

'/--データが残ってたりしないよう、先にデータを消去--/'
mWB.Sheets("処理結果").Select
mWB.Sheets("処理結果").Range(Rows(3), Rows(Rows.Count)).Clear
mWB.Sheets("output").Select
mWB.Sheets("output").Range(Rows(2), Rows(Rows.Count)).Clear

yR = 3
yO = 2

strFN = Dir(strFP & "\*.xls*")

Do Until strFN = ""
    Select Case strFN
        '/--見つけたファイルがマクロファイルの場合は何もしない--/'
        Case mWB.Name
        
        '/--見つけたファイルがマクロファイル以外の場合--/'
        Case Else
            Set iWB = Workbooks.Open(strFP & "\ " & strFN)
            cWS = iWB.Worksheets.Count
            For s = 2 To cWS
                Set iWS = iWB.Sheets(s)
                strNo1 = ""
                strNo2 = ""
                strNo3 = ""
                strNo4 = ""
                strName = ""
                lngFromY = 0
                intFromM = 0
                lngToY = 0
                intToM = 0
                
                yI = iWS.Cells(Rows.Count, 1).End(xlUp).Row
                For y = 2 To yI
                    '/--インプット情報を取得--/'
                    strNo1 = iWS.Cells(y, 1)
                    strNo2 = iWS.Cells(y, 2)
                    strNo3 = iWS.Cells(y, 3)
                    strNo4 = iWS.Cells(y, 4)
                    strName = iWS.Cells(y, 5)
                    lngFromY = CLng(iWS.Cells(y, 6))
                    intFromM = CInt(iWS.Cells(y, 7))
                    lngToY = CLng(iWS.Cells(y, 8))
                    intToM = CInt(iWS.Cells(y, 9))
                    
                    '/--データの期間を計算--/'
                    dateFrom = DateSerial(lngFromY, intFromM, 1)
                    dateTo = DateSerial(lngToY, intToM, 1)
                    lngDiffM = DateDiff("m", dateFrom, dateTo)
                    
                    '/--検証用シートに共通項目だけ転記--/'
                    With mWB.Sheets("処理結果")
                        .Cells(yR, 1).Value = iWB.Name
                        .Cells(yR, 2).Value = iWS.Name
                        .Cells(yR, 3).Value = y
                        .Cells(yR, 4).Value = strNo1
                        .Cells(yR, 5).Value = strNo2
                        .Cells(yR, 6).Value = strNo3
                        .Cells(yR, 7).Value = strNo4
                        .Cells(yR, 8).Value = strName
                        .Cells(yR, 9).Value = lngFromY
                        .Cells(yR, 10).Value = intFromM
                        .Cells(yR, 11).Value = lngToY
                        .Cells(yR, 12).Value = intToM
                    End With
                    
                    '/--データ期間ごとの処理--/'
                    Select Case lngDiffM
                        Case Is < 12   '/--同月含む12か月以内の場合--/'
                            '/--検証用シートに1レコード分だけ転記--/'
                            With mWB.Sheets("処理結果")
                                .Cells(yR, 13).Value = lngFromY
                                .Cells(yR, 14).Value = intFromM
                                .Cells(yR, 15).Value = lngToY
                                .Cells(yR, 16).Value = intToM
                            End With
                            '/--アウトプット用シートに1レコード分だけ転記--/'
                            With mWB.Sheets("Output")
                                .Cells(yO, 1).Value = strNo1
                                .Cells(yO, 2).Value = strNo2
                                .Cells(yO, 3).Value = strNo3
                                .Cells(yO, 4).Value = strNo4
                                .Cells(yO, 5).Value = strName
                                .Cells(yO, 6).Value = lngFromY
                                .Cells(yO, 7).Value = intFromM
                                .Cells(yO, 8).Value = lngToY
                                .Cells(yO, 9).Value = intToM
                            End With
                            yR = yR + 1
                            yO = yO + 1
                            
                        Case Else      '/--同月含む13か月以上の場合--/'
                            
                            '/--何年跨いでいるかの期間を取得--/'
                            lngDiffY = DateDiff("yyyy", dateFrom, dateTo)
                            
                            '/--年跨ぎ分の周回処理--/'
                            For n = 0 To lngDiffY
                                '/--検証用シートに対象期間(年)+n年の情報を転記--/'
                                With mWB.Sheets("処理結果")
                                    .Cells(yR, n * 4 + 13).Value = lngFromY + n
                                    If n = 0 Then
                                        .Cells(yR, n * 4 + 14).Value = intFromM
                                    Else
                                        .Cells(yR, n * 4 + 14).Value = 1
                                    End If
                                    .Cells(yR, n * 4 + 15).Value = lngFromY + n
                                    If n = lngDiffY Then
                                        .Cells(yR, n * 4 + 16).Value = intToM
                                    Else
                                        .Cells(yR, n * 4 + 16).Value = 12
                                    End If
                                End With
                                
                                '/--アウトプット用シートに対象期間(年)+n年の情報を転記--/'
                                With mWB.Sheets("Output")
                                    .Cells(yO, 1).Value = strNo1
                                    .Cells(yO, 2).Value = strNo2
                                    .Cells(yO, 3).Value = strNo3
                                    .Cells(yO, 4).Value = strNo4
                                    .Cells(yO, 5).Value = strName
                                    .Cells(yO, 6).Value = lngFromY + n
                                    If n = 0 Then
                                        .Cells(yO, 7).Value = intFromM
                                    Else
                                        .Cells(yO, 7).Value = 1
                                    End If
                                    .Cells(yO, 8).Value = lngFromY + n
                                    If n = lngDiffY Then
                                        .Cells(yO, 9).Value = intToM
                                    Else
                                        .Cells(yO, 9).Value = 12
                                    End If
                                    yO = yO + 1
                                End With
                            Next n
                            yR = yR + 1
                    End Select
                    
                Next y
                Set iWS = Nothing
            Next s
    End Select
    iWB.Close
    Set iWB = Nothing
    strFN = Dir()
Loop

'/--アウトプット用シートを新規ブックにコピーして保存--/'
Application.DisplayAlerts = False
Sheets("Output").Select
Sheets("Output").Copy
ActiveWorkbook.SaveAs Filename:=strFP & "\output.xls", FileFormat:=xlExcel8
ActiveWindow.Close
Application.DisplayAlerts = True

Set mWB = Nothing

End Sub


3.マクロ処理結果

処理結果のシートには検証のデータが、

検証用のシート


Outputのシートには実際にファイル出力されるデータが転記され

出力されるシート


インプットファイルと同じフォルダにoutput.xlsというファイルが出力されます。

出力されたファイル


■マクロ解説

1.データの期間を計算

'/--データの期間を計算--/'
dateFrom = DateSerial(lngFromY, intFromM, 1)
dateTo = DateSerial(lngToY, intToM, 1)
lngDiffM = DateDiff("m", dateFrom, dateTo)

・dateFrom = DateSerial(lngFromY, intFromM, 1)

年(lngFromY)、月(intFromM)、日(1)で日付のシリアル値(1900/1/1からの経過日数)を日付型のdateFromへ格納しています。
lngFromY:対象期間(前)(年)
intFromM:対象期間(前)(月)
同じようにdateTo = DateSerial(lngToY, intToM, 1)で対象期間(後)の年月日も日付型で格納しています。

・lngDiffM = DateDiff("m", dateFrom, dateTo)

dateFromからdateToまでの期間を単位で計算し、数値型lngDiffMへ格納しています。


2.13か月以上の処理

lngDiffMが12以上(同月はlngDiffM=0となるので、13か月目は12となります。)は13か月以上として処理します。

'/--何年跨いでいるかの期間を取得--/'
lngDiffY = DateDiff("yyyy", dateFrom, dateTo)

'/--年跨ぎ分の周回処理--/'
For n = 0 To lngDiffY
    '/--アウトプット用シートにfrom対象期間+n年の情報を転記--/'
    With mWB.Sheets("Output")
        .Cells(yO, 1).Value = strNo1
        .Cells(yO, 2).Value = strNo2
        .Cells(yO, 3).Value = strNo3
        .Cells(yO, 4).Value = strNo4
        .Cells(yO, 5).Value = strName
        .Cells(yO, 6).Value = lngFromY + n
        If n = 0 Then
            .Cells(yO, 7).Value = intFromM
        Else
            .Cells(yO, 7).Value = 1
        End If
        .Cells(yO, 8).Value = lngFromY + n
        If n = lngDiffY Then
            .Cells(yO, 9).Value = intToM
        Else
            .Cells(yO, 9).Value = 12
        End If
        yO = yO + 1
    End With
Next n

・lngDiffY = DateDiff("yyyy", dateFrom, dateTo)

dateFromからdateToまでの期間を単位で計算し、数値型lngDiffMへ格納しています。
これにより何年跨いだかが判明します。

・For n = 0 To lngDiffY

跨いだ年数分周回させます。

・.Cells(yO, 6).Value = lngFromY + n

1年目はn=0なので「lngFromY:対象期間(前)(年)」の値が入り、
2年目はn=1となり「lngFromY」の1年後の年が入ります。
このようにnが+1されるごとに1年後の値が入るようになります。

・If n = 0 Then
.Cells(yO, 7).Value = intFromM
 Else
.Cells(yO, 7).Value = 1
 End If

1年目(n=0)は「intFromM:対象期間(前)(月)」の値が入りますが、2年目以降は対象期間(前)(月)は1月であるべきなので、n>0は1が入るようにしています。

・If n = lngDiffY Then
.Cells(yO, 9).Value = intToM
 Else
.Cells(yO, 9).Value = 12
 End If

最終年目(n=lngDiffY)は「intFromM:対象期間(後)(月)」の値が入りますが、最終年-1年目までは対象期間(後)(月)は12月であるべきなので、n<lngDiffYは12が入るようにしています。

・yO = yO + 1

意外と忘れがちですが、13か月以上の場合は年毎に分割(インプット1に対してアウトプット複数)なので、この周回の中で「yO:Outputシートの行」を+1していきます。


このようにDateSerial、DateDiffを組み合わせ期間を取得、その期間の中で年と月をどのよう表現すればよいか考えると条件にある

2.インプットファイル、“対象期間(前)”と“対象期間(後)”の月数が、12か月以内のものは、そのまま転記し、13か月以上のものは"1月~12月”の表示形式で最大12か月の期間で行を分ける。(1行の内、期間は年を跨がない)

を達成できるようになります。


↓よろしければクリックをお願いします!

TOPページへ戻る


■社内DX案件紹介

【社内DX案件紹介】アンケートの集計-1-

【社内DX案件紹介】アンケートの集計-2-

【社内DX案件紹介】架電内容ごとの情報振り分け-1-

【社内DX案件紹介】架電内容ごとの情報振り分け-2-

【社内DX案件紹介】2つのファイルの内容を比較する

【社内DX案件紹介】封入物の重さによって印刷会社を変える

【社内DX案件紹介】値の入っているシートのみ印刷する


■社内DXの進め方

【社内DXの進め方】ブログの目的(会社が求めるDX)

【社内DXの進め方】社内DXの推進について

【社内DXの進め方】社内DXは具体的に何をすればよいのか?

【社内DXの進め方】なぜ今Excelか?


2022年12月30日金曜日

【社内DX案件紹介】封入物の重さによって印刷会社を変える

 コスト削減において、もっとも大きいな削減は人件費となりますが、通常の業務を少しDXすることでコスト削減を図ることが可能です。


■社内DXの依頼内容

お客様に送る郵送物を、封入物の重さによって印刷会社1・2・3に分類しコスト削減を図りたい。

全ての封入物の重さから印刷会社を1~3で分類するマクロ


■社内DXの条件

・封入物はA~Eの5種類

 封入物A:2g

 封入物B:3g

 封入物C:5g

 封入物D:10g

 封入物E:15g


・郵送物の重さによって印刷会社を変える

 15g未満:印刷会社1

 35g未満:印刷会社2

 35g以上:印刷会社3


・リストは横方向に順不同で封入物が記載されている

封入物が記載された顧客リスト


■諸元

・封入物のリストから重さを検索する


・検索には連想配列(Dictionaryオブジェクト)を使用して検索を高速化する


・封入物の総重量によって印刷会社を1~3で設定


■作成方法

1.シート「リスト」に顧客情報と封入物のリストを用意(今回は項番1~100でセット)

シート「リスト」 封入物が順不同でセットされた100名分の顧客リスト

2.シート「封入物リスト」に封入物名と重さのリストを用意

シート「封入物リスト」 封入物A~Eとその重さが記載されたリスト

3.実際にマクロを書いていく

Sub Insatsu_List()
    Dim y As Long           '/--行周回用のカウンタ--/'
    Dim x As Integer        '/--列周回用のカウンタ--/'
    
    Dim dicFunyu As Object  '/--封入物の連想配列用オブジェクト--/'
    Dim strKey As String    '/--検索用キー格納--/'
    Dim lngOmosa As Long    '/--重さを格納--/'
    Dim strKaisha As String '/--印刷会社名--/'
    
    '/--オブジェクトを連想配列(Dictionary)としてセット--/'
    Set dicFunyu = CreateObject("Scripting.Dictionary")
    
    '/--連想配列作成--/'
    For y = 2 To 6
        strKey = Sheets("封入物リスト").Cells(y, 1).Value
        lngOmosa = Sheets("封入物リスト").Cells(y, 2).Value
        '/--連想配列に検索キー(strKey)と値(lngOmosa)を格納--/'
        dicFunyu.Add strKey, lngOmosa
    Next y
    
    '/--リスト内のデータに重さ、印刷会社を記入--/'
    For y = 2 To 101
        lngOmosa = 0
        For x = 3 To 7
            strKey = Sheets("リスト").Cells(y, x).Value
            lngOmosa = lngOmosa + dicFunyu.Item(strKey)
        Next x
        
        Sheets("リスト").Cells(y, 8) = lngOmosa
        
        Select Case lngOmosa
            Case Is < 15
                strKaisha = "1"
            Case Is < 35
                strKaisha = "2"
            Case Is >= 35
                strKaisha = "3"
        End Select
        
        Sheets("リスト").Cells(y, 9) = strKaisha
        
    Next y
    
    Set dicOmosa = Nothing
    
    
End Sub


■マクロ解説

1.連想配列の作成

    '/--オブジェクトを連想配列(Dictionary)としてセット--/'
    Set dicFunyu = CreateObject("Scripting.Dictionary")
    
    '/--連想配列作成--/'
    For y = 2 To 6
        strKey = Sheets("封入物リスト").Cells(y, 1).Value
        lngOmosa = Sheets("封入物リスト").Cells(y, 2).Value
        '/--連想配列に検索キー(strKey)と値(lngOmosa)を格納--/'
        dicFunyu.Add strKey, lngOmosa
    Next y

・Set dicFunyu = CreateObject("Scripting.Dictionary")

dicFunyuというオブジェクトをDictionaryとしてセットします。

※Officeの365とか、なぜか旧Verと参照設定が異なる場合があるので、基本参照設定を使わないで作成しています


dicFunyu.Add strKey, lngOmosa

連想配列に検索キー(strKey)と値(lngOmosa)を代入します。

ルールとしては必ず検索キー1に対して値1となること

Excel関数のVlookupとかみたいに検索キー1つに対して複数の値をとることはできません。

※アイデア次第でやる方法はいくつかありますが別の機会に。


2.重さの取得

            strKey = Sheets("リスト").Cells(y, x).Value
            lngOmosa = lngOmosa + dicFunyu.Item(strKey)


・strKey = Sheets("リスト").Cells(y, x).Value

strKey に封入物名を代入します。


・lngOmosa = lngOmosa + dicFunyu.Item(strKey)

検索キー(strKey)からItem(値)を取り出します。


いかがでしょうか。

このように、少しのアイデアで十分に社内DXが実現できるようになります。


↓よろしければクリックをお願いします!

TOPページへ戻る


■社内DX案件紹介

【社内DX案件紹介】アンケートの集計-1-

【社内DX案件紹介】アンケートの集計-2-

【社内DX案件紹介】架電内容ごとの情報振り分け-1-

【社内DX案件紹介】架電内容ごとの情報振り分け-2-

【社内DX案件紹介】2つのファイルの内容を比較する

【社内DX案件紹介】データの期間によってレコードを分割しファイル出力する

【社内DX案件紹介】値の入っているシートのみ印刷する


■社内DXの進め方

【社内DXの進め方】ブログの目的(会社が求めるDX)

【社内DXの進め方】社内DXの推進について

【社内DXの進め方】社内DXは具体的に何をすればよいのか?

【社内DXの進め方】なぜ今Excelか?

2022年12月15日木曜日

【社内DX案件紹介】架電内容ごとの情報振り分け-2-

 前回の続きで今回は実際にマクロを書いていきます。

前> 【社内DX案件紹介】架電内容ごとの情報振り分け-1-


今回作るマクロ

前回のおさらいですが、

依頼内容は

データベースの情報を条件ごとに振り分ける

という話をしました。

データベースの情報を架電内容ごとに振り分ける

実際の処理としてはシンプルで

1.シート「抽出データ」のデータを取得する

2.取得したデータを条件に合ったシートへ転記する

の2点。
処理の流れ 条件だけ赤字


ただこの「条件」の作り方が今回のポイントでIF文ではなく、各カラムの情報①~④を繋げて判定する方法で行きたいと思います。
分類の条件

まずは全体像です。
本当はデータベースからデータをとって分類し、最後エクセルのファイルで出力するのですが、今回はシート「抽出データ」にある架電内容のデータを各シート「パターンA」~「パターンL」に情報を転記するマクロとしました。
マクロのエクセルシート


次にマクロの全体です。
Sub Sample2()

Dim intSheet As Integer         '/--シート番号--/'
Dim strSheetName As String      '/--シート名--/'
Dim lngMaxY As Long             '/--シート「抽出データ」の最大行数--/'
Dim lngY As Long                '/--行周回用カウンタ--/'
Dim lngMaxY2 As Long            '/--転記先シートの最大行数--/'
Dim intMaxX As Integer          '/--シート「抽出データ」の最大列数--/'
Dim intX As Integer             '/--列周回用カウンタ--/'
Dim strKaden As String          '/--架電理由--/'
Dim strKoutei As String         '/--工程名称--/'
Dim strNAT As String            '/--NAT--/'
Dim strIshi As String           '/--意思確認--/'
Dim strHantei As String         '/--条件判定--/'

'/--シート「抽出データ」の最大行数・最大列数を取得--/'
lngMaxY = Sheets("抽出データ").Cells(Rows.Count, 1).End(xlUp).Row
intMaxX = Sheets("抽出データ").Cells(1, Columns.Count).End(xlToLeft).Column

'/--カラム名を各シートに転記--/'
For intSheet = 2 To ActiveWorkbook.Sheets.Count
    For intX = 1 To intMaxX
        Sheets(intSheet).Cells(1, intX).Value = Sheets("抽出データ").Cells(1, intX).Value
    Next intX
Next intSheet

'/--シート「抽出データ」の最大行数分周回--/'
For lngY = 2 To lngMaxY
    strSheetName = ""
    strKaden = "0"
    strKoutei = "0"
    strNAT = "0"
    strIshi = "0"
    strHantei = "0000"

    strKaden = Sheets("抽出データ").Cells(lngY, 1).Value
    strKoutei = Sheets("抽出データ").Cells(lngY, 15).Value
    strNAT = Sheets("抽出データ").Cells(lngY, 19).Value
    strIshi = Sheets("抽出データ").Cells(lngY, 20).Value
    
    '/--架電理由の条件格納--/'
    Select Case strKaden
        Case "自動更新"
            strKaden = "1"
        Case "OB対象外"
            strKaden = "1"
        Case "審査"
            strKaden = "1"
        Case "電話・資料請求"
            strKaden = "2"
        Case "窓口(新規)"
            strKaden = "3"
        Case "不明"
            strKaden = "4"
        Case "乗換"
            strKaden = "4"
        Case "利用率高"
            strKaden = "4"
        Case "未成年"
            strKaden = "4"
        Case "ハイクラス"
            strKaden = "5"
        Case Else
            strKaden = "9"
    End Select
    
    '/--工程名称の条件格納--/'
    Select Case strKoutei
        Case "電話・本人宛NAT"
            strKoutei = "1"
        Case "電話・事前不備有"
            strKoutei = "2"
        Case "電話・本人宛不備"
            strKoutei = "3"
        Case "電話・同意"
            strKoutei = "4"
        Case "電話・資料請求"
            strKoutei = "5"
        Case Else
            strKoutei = "9"
    End Select
    
    '/--NATの条件格納--/'
    If strNAT = "" Then
        strNAT = "1"
    Else
        strNAT = "9"
    End If
    
    '/--意思確認の条件格納--/'
    If strIshi = "1" Then
        strIshi = "1"
    Else
        strIshi = "9"
    End If
    
    '/--各条件を結合--/'
    strHantei = strKaden & strKoutei & strNAT & strIshi
    
    '/--条件によるパターン判定--/'
    Select Case Left(strHantei, 2)
        Case "11"
            Select Case strHantei
                Case "1111"
                    strSheetName = "パターンA"
                Case Else
                    strSheetName = "パターンL"
            End Select
        Case "12"
            strSheetName = "パターンB"
        Case "13"
            strSheetName = "パターンC"
        Case "14"
            strSheetName = "パターンD"
        Case "15"
            strSheetName = "パターンE"
        Case "21"
            strSheetName = "パターンG"
        Case "22"
            strSheetName = "パターンH"
        Case "23"
            strSheetName = "パターンF"
        Case Else
            Select Case Left(strHantei, 1)
                Case "3"
                    strSheetName = "パターンI"
                Case "4"
                    strSheetName = "パターンJ"
                Case "5"
                    strSheetName = "パターンK"
                Case Else
                    strSheetName = "パターンL"
            End Select
    End Select
    
    '/--転記先シートの最大行数を取得--/'
    lngMaxY2 = Sheets(strSheetName).Cells(Rows.Count, 1).End(xlUp).Row + 1
    
    '/--転記先シートへデータを転記--/'
    For intX = 1 To intMaxX
        Sheets(strSheetName).Cells(lngMaxY2, intX).Value = Sheets("抽出データ").Cells(lngY, intX).Value
    Next intX
        
Next lngY

End Sub

それぞれのパートで説明すると
'/--シート「抽出データ」の最大行数・最大列数を取得--/'
lngMaxY = Sheets("抽出データ").Cells(Rows.Count, 1).End(xlUp).Row
intMaxX = Sheets("抽出データ").Cells(1, Columns.Count).End(xlToLeft).Column
ここはシート「抽出データ」の1列目の値がある最終行1行目の値がある最終列を取得しています。
まず
.Cells(Rows.Count, 1).End(xlUp).Row
ですが、
Row.Count:Excelの最後の行(1048576)
1      :1列目
.End(xlUp):最後の行から上方向に
.Row    :値のある行番号をとる
こんな意味となります。

.Cells(1, Columns.Count).End(xlToLeft).Column
ここもほとんど同じで
Columns.Count:Excelの最後の列(16384)
.End(xlToLeft)  :最後の列から左方向に
.Column    :値のある列番号をとる
こんな意味となります。

'/--架電理由の条件格納--/'
Select Case strKaden
    Case "自動更新"
        strKaden = "1"
    Case "OB対象外"
        strKaden = "1"
    Case "審査"
        strKaden = "1"
    Case "電話・資料請求"
        strKaden = "2"
    Case "窓口(新規)"
        strKaden = "3"
    Case "不明"
        strKaden = "4"
    Case "乗換"
        strKaden = "4"
    Case "利用率高"
        strKaden = "4"
    Case "未成年"
        strKaden = "4"
    Case "ハイクラス"
        strKaden = "5"
    Case Else
        strKaden = "9"
End Select
ここは①架電理由を1~5、9で分類してstrKadenに入れています。
同様にstrKoutei(工程名称)、strNAT(NAT)、strIshi(意思確認)も下図の条件に合わせて分類していきます。
分類の条件 赤字でパターン番号付与

'/--各条件を結合--/'
strHantei = strKaden & strKoutei & strNAT & strIshi

'/--条件によるパターン判定--/'
Select Case Left(strHantei, 2)
    Case "11"
        Select Case strHantei
            Case "1111"
                strSheetName = "パターンA"
            Case Else
                strSheetName = "パターンL"
        End Select
    Case "12"
        strSheetName = "パターンB"
    Case "13"
        strSheetName = "パターンC"
    Case "14"
        strSheetName = "パターンD"
    Case "15"
        strSheetName = "パターンE"
    Case "21"
        strSheetName = "パターンG"
    Case "22"
        strSheetName = "パターンH"
    Case "23"
        strSheetName = "パターンF"
    Case Else
        Select Case Left(strHantei 1)
            Case "3"
                strSheetName = "パターンI"
            Case "4"
                strSheetName = "パターンJ"
            Case "5"
                strSheetName = "パターンK"
            Case Else
                strSheetName = "パターンL"
        End Select
End Select

ここからは実際にA~Lのパターン分けになります
①②③④を繋げたstrHanteiがどうだったか?をSelect文で分類していますが、
①②③④の値が
1111・・・パターンA
12xx・・・パターンB(xはどの値でもよい)
13xx・・・パターンC
14xx・・・パターンD
15xx・・・パターンE
23xx・・・パターンF
21xx・・・パターンG
22xx・・・パターンH
3xxx・・・パターンI
4xxx・・・パターンJ
5xxx・・・パターンK
それ以外・・パターンL
となります。

ここでポイントですが、パターンA、I~K以外は①②で判定できる。という点です。

なので基本は
Select Case Left(strHantei, 2)
で左2文字分で判定し、
Left(strHantei, 2)の値が”11”の時は
Select Case strHantei
    Case "1111"
        strSheetName = "パターンA"
    Case Else
        strSheetName = "パターンL"
End Select
で4文字全てを条件とし、逆にLeft(strHantei 2)の値が”23”以降であれば
Select Case Left(strHantei, 1)
    Case "3"
        strSheetName = "パターンI"
    Case "4"
        strSheetName = "パターンJ"
    Case "5"
        strSheetName = "パターンK"
    Case Else
        strSheetName = "パターンL"
End Select
で左1文字だけで判定することでパターンA~Lの全てを分類できるようになります。

'/--転記先シートの最大行数を取得--/'
lngMaxY2 = Sheets(strSheetName).Cells(Rows.Count, 1).End(xlUp).Row + 1

'/--転記先シートへデータを転記--/'
For intX = 1 To intMaxX
    Sheets(strSheetName).Cells(lngMaxY2, intX).Value = Sheets("抽出データ").Cells(lngY, intX).Value
Next intX
で最後は転記先のシートの最大行数を取得して、その1つ下(+1)したところに、その行の値を転記して1行分が終了します。
あとはそれをシート「抽出データ」の全レコードで実施して終了になります。

これで案件2の紹介は終了します。


↓よろしければクリックをお願いします!

2022年12月13日火曜日

【社内DX案件紹介】架電内容ごとの情報振り分け-1-

 今回も実際に依頼された社内DX案件を紹介します。


■案件2 架電内容ごとの情報振り分け

依頼内容

社内のデータベースにあるコールセンターのデータを特定の条件で振り分けてもらいたいというもの。

今はスタッフが手作業で振り分けていたようだが、それをVBAで何とかしたい。というもの。

つまりこれを

データベースのデータを手作業で振り分け

こうしたいということ

データベースの情報を自動で振り分け

実際のデータはこんな感じなのですが、

約20列のデータベースのデータ

これを

・架電理由

・工程名称

・NAT

・意思確認

データベースの条件を取得する箇所

の値が以下の条件に当てはまるようなパターン処理が必要となる。

12パターンの条件分岐

というわけで今回はこんな処理をなるべくシンプルになるようなマクロを作成します。

今回作るマクロ

シート「抽出データ」にある情報をパターン毎に分類し、各シートへ転記するマクロ

実際の処理の流れは非常に簡単で

1.シート「抽出データ」のデータを取得する

2.取得したデータを条件に合ったシートへ転記する

処理のながれ

この2点だけです。

ただ、この”条件”が非常に厄介です。

処理のながれ 条件だけ赤字

先ほどの分類の条件をもう一度確認しますがこんな感じです。

分類の条件 再掲

これをフローチャートで表すとこんな感じで複雑です。

条件のフローチャート

更にこれをマクロで書くとこうなります。

    strKaden = 架電理由の値を格納

    strKoutei = 工程名称の値を格納

    strNAT = NATの値を格納

    strIshi = 意思確認の値を格納

とすると、

If strKaden = "自動更新" Or strKaden = "OB対象外" Or strKaden = "審査" Then
	If strKoutei = "電話・本人宛NAT" Then
		If strNAT = "" And strIshi = "1" Then
		strSheetName = "パターンA"
		Else
		strSheetName = "パターンL"
		End If
	ElseIf strKoutei = "電話・事前不備有" Then
		strSheetName = "パターンB"
	ElseIf strKoutei = "電話・本人宛不備" Then
		strSheetName = "パターンC"
	ElseIf strKoutei = "電話・同意" Then
		strSheetName = "パターンD"
	ElseIf strKoutei = "電話・資料請求" Then
		strSheetName = "パターンE"
	Else
		strSheetName = "パターンL"
	End If
ElseIf strKaden = "電話・資料請求" Then
	If strKoutei = "電話・本人宛NAT" Then
		strSheetName = "パターンG"
	ElseIf strKoutei = "電話・事前不備有" Then
		strSheetName = "パターンH"
	ElseIf strKoutei = "電話・本人宛不備" Then
		strSheetName = "パターンF"
	Else
		strSheetName = "パターンL"
	End If
ElseIf strKaden = "窓口(新規)" Then
	strSheetName = "パターンI"
ElseIf strKaden = "不明" Or strKaden = "乗換" Or strKaden = "利用率高" _ 
		Or strKaden = "未成年" Then
	strSheetName = "パターンJ"
ElseIf strKaden = "ハイクラス" Then
	strSheetName = "パターンK"
Else
	strSheetName = "パターンL"
End If

かなり見づらいコードになりますね。


なので、今回は少しやり方を変えて、

架電理由:①

工程名称:②

NAT:③

意思確認:④

として、①②③④の値からパターン分けしていきたいと思います。

分類の条件 各番号によるパターン化

どういう考え方かというと、ASN.1の列挙型(ENUMERATED)に近いのですが、

①架電理由=自動更新・・・1

②工程名称=電話・本人宛NAT・・・1

③NAT=空欄・・・1

④意思確認=1・・・1

である場合、①②③④は”1111”となります。

この①②③④が”1111”の時はパターンAと判定する。

①②③④が"12xx"の時はパターンB、"15xx"の時はパターンEとすることで、複雑な条件式を作らなくてもよくなり、また条件が増えた場合においても修正が簡易となります。

※xは不問(どんな値でもよい)


このような場合はどのように書いていくのか、次回は実際にコードを書いてみたいと思います。

↓よろしければクリックをお願いします!

次 > 【社内DX案件紹介】架電内容ごとの情報振り分け-2-


TOPページに戻る



■社内DX案件紹介

【社内DX案件紹介】アンケートの集計-1-

【社内DX案件紹介】アンケートの集計-2-

【社内DX案件紹介】2つのファイルの内容を比較する

【社内DX案件紹介】封入物の重さによって印刷会社を変える

【社内DX案件紹介】データの期間によってレコードを分割しファイル出力する

【社内DX案件紹介】値の入っているシートのみ印刷する


■社内DXの進め方

【社内DXの進め方】ブログの目的(会社が求めるDX)

【社内DXの進め方】社内DXの推進について

【社内DXの進め方】社内DXは具体的に何をすればよいのか?

【社内DXの進め方】なぜ今Excelか?


2022年11月28日月曜日

【マクロVBA】VBA_TIPS-02 Select文とIf文

今回はSelect文とIf文の使い分けについて話します。

例えばAの値に2が入っているとして、このAの値によって処理を変えるとします。
これをSelect文で表現すると
A = "こんにちは"
Select Case A
    Case "おはよう"
        MsgBox "Aはおはようです"
    Case "こんにちは"
        MsgBox "Aはこんにちはです"
    Case "こんばんわ"
        MsgBox "Aはこんばんわです"
    Case "おやすみなさい"
        MsgBox "Aはおやすみなさいです"
    Case Else
        MsgBox "Aはそれ以外です"
End Select
となります。If文で表現すると
A = "こんにちは"
If A = "おはよう" Then
    MsgBox "Aはおはようです"
ElseIf A = "こんにちは" Then
    MsgBox "Aはこんにちはです"
ElseIf A = "こんばんわ" Then
    MsgBox "Aはこんばんわです"
ElseIf A = "おやすみなさい" Then
    MsgBox "Aはおやすみなさいです"
Else
    MsgBox "Aはそれ以外です"
End If
となります。

どちらで書いても結果は
メッセージボックス Aはこんにちはです

で変わりません。
ではSelect文とIf文をどのように使い分ければよいのか?どちらを使うべきなのか?ですが、Select文を使えるのであればSelect文のほうが処理が速いので良い。という話を聞いたことがあります。
恐らく今のPC性能だとあまり気にする差ではないと思いますが、私はたまに100万行とかのCSVファイルを扱うときがあるので、なるべくSelect文を使うようにしています。

ではSelect文とIf文の明確な違いは何か?ですが、
Select:変数は1つしかできない
If   :変数を複数使うことができる
ですね。

Select文の場合はAの値から選ぶしかできず、例えば
Select Case A
とした場合、
Case A="こんにちは"
だとAがこんにちはのとき
Case A<>"こんにちは"
だとAがこんにちはでないとき
という感じでSelect Caseで決めたものに対して選ぶことしかできません。

逆にIf文を使うと
A = "こんにちは"
B = "こんにちわ"
If A = "おはよう" Then
    MsgBox "Aはおはようです"
ElseIf A = "こんにちは" And B = "こんにちわ" Then
    MsgBox "AもBもこんにちはです"
Else
    MsgBox "Aはそれ以外です"
End If
のように1つのIf文で複数の変数から条件を設定することが可能です。

このようにSelect文とIf文の違いを理解しておくことで、場面場面によって最適なやり方を考えることができるようになります。




2022年11月27日日曜日

【マクロVBA】VBA_TIPS-01 RangeとCells

 今回は案件で実際に使ったマクロのコードについて紹介します。


VBAの本やサイトだと仮にB2セルを指定する場合

ActiveSheet.Range("B2").Select

と記載される場合が多いですが、今回

ActiveSheet.Cells(2,2).Select

とRangeのところをCellsで記載しています。


この違いと便利な使い道について紹介します。


■Rangeオブジェクト

Excelの標準の表記(列をA~XFD、行を1~1048576で表した形式)なります。

ActiveSheet.Range("B2").Select

となる場合は、

”B"列目の"2"行目

を表すことになります。

RangeオブジェクトのB2セル

ダイレクトにセルを指定する場合にはわかりやすいので便利ですが、For文等で各行・列を周回する場合などセルの位置が可変である場合にはあまり適しません。

例えばA1セルからD1セルまでそれぞれ連続で選択していくとすると、

ActiveSheet.Range("A1").Select
ActiveSheet.Range("B1").Select
ActiveSheet.Range("C1").Select
ActiveSheet.Range("D1").Select

と記載するか、Offsetを利用して

For x = 1 To 3
    ActiveSheet.Range("A1").Offset(0, x).Active
Next x

と記載する必要があり、少々面倒です。

そこで使用するのがCellsオブジェクトによる記載方法になります。


■Cellsオブジェクト

こちらはExcelのオプションで設定できるR1C1参照形式による表記になります。

Excelの[ファイル]-[オプション]-[数式]から選択できます。

R1C1形式の設定方法

こちらをチェックするとExcelの表示がこう変わります。
R1C1形式のExcel

で、こちらはR1C1形式(R:Rows=行、C:Columns=列)となりますので、RagngeオブジェクトでB2を表現する場合は

”B"目の"2"

だったものが

R1C1形式では

”2"目の"2"

と行列が逆になります。

CellsオブジェクトはこのR1C1形式での表記となりますので、先ほどのA1~D1セルを連続で選択数場合

For x = 1 To 4
    ActiveSheet.Cells(1, x).Select
Next x

で良くなります。


このように、セル番地が可変になる場合にはCellsオブジェクト、不変の場合はRangeオブジェクトを使用するのが良いと思います。

※正直、Cellsで統一したほうがきれいなのは確かですが。


■範囲の指定

マクロで罫線を引いたり、セルを塗りつぶしたりする場合があります。

しかもセルの位置が可変の場合はどうすればよいか?

そう、そんなときはRangeとCellsの合わせ技です。


例えばB2~C3セルを範囲で選択したい場合、Rangeオブジェクトであれば

ActiveSheet.Range("B2:C3").Select

で良いのですが、Cellsオブジェクトだと

ActiveSheet.Cells(2,2).Select

だとB2セルしか選択できず、複数範囲の選択ができません。


Cellsオブジェクトを使用して複数範囲を選択する以下の場合は

Cellsオブジェクトを使って範囲指定する場合のイメージ

範囲選択できるRangeオブジェクトの中にCellsオブジェクトを入れることで範囲が表現できます。

ActiveSheet.Range(Cells(2,2),Cells(3,3)).Select

このCellsの部分を変数で可変にすることで、範囲指定を複数回実施したりすることが可能になります。


DXを進めるうえで、自動で表を作ったり、自動でグラフを作ったり、自動でやる部分が多くなってきます。

そういったときにこの可変でも範囲指定ができることを知っているかどうかで、仕事の質が変わってきますので、ぜひ覚えておいてください。


TOPページに戻る


■関連ページ

【マクロVBA】VBA_TIPS-02 Select文とIf文

【マクロVBA】VBA_TIPS-03 マクロの可読性