別シートにまたぐのは可能?並び替えのコード設計

vbanarabisheetmatagieyecatc

エクセル 並び替えマクロツールで、「別シートにまたぐ」も実行できるか?VBAコードの作成を考えます。
並び替えトラブルが起こりにくいコード作りが必要です。

こんにちは じゅんぱ店長 (@junpa33) です。

VBAを使って、エクセルのセルデータを「別シートをまたいで」並び替えを行う方法を考えます。

各シート毎に行うのなら、もちろんそれは、エクセルの標準搭載の「並び替え」機能で可能です。

操作系はシート単位になっていて、シートを変更する毎に ” リボンからの「並び替え」窓の立ち上げ ” を行う必要があります。

それを現在作成中の「エクセル並び替えマクロツール」で、この不便さが何とか良くならないかを考えてみます。

先に結論を言っておきます。

VBAコード的には、シートまたぎは可能です。

が、想定する並び方とは違う結果になる可能性が大きく、

ゆえに、元データを壊してしまうことになりかねません。

並び替えマクロ 記事階層

この記事番号は3番です。

エクセル搭載の並び替え機能は「シートまたぎ」が禁じ手

エクセルでは「シートまたぎ」を行なおうとすると、どのようになるのか現状確認をしてみます。

題材として、このような表を想定します。

vbanarabisheetmatagi001

エクセルの機能「並び替え」からの禁じ手検証

これはもうよくご存じだと思いますが、シートを複数同時選択すると、リボン操作がほぼOFFになってしまいます。

vbanarabisheetmatagi001

この状態では全く操作することが出来ませんので、検証以前の問題です。つまりこれによっても「だめですよ」と言っているとわかります。

エクセルの並び替え機能をマクロの記録から禁じ手検証

並び替え機能がどのようにVBAで記述されるかをマクロの記録で確認します。

元の表
「ポイント」昇順で並べ替え

記録したマクロ(VBAコード)はこのようになっています。

VBA
Sub Macro並び替えtest1()
'
' Macro並び替えtest Macro
'

'
    Range("A1").Select
    ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields.Clear
    ActiveWorkbook.Worksheets("Sheet1").Sort.SortFields _
        .Add Key:=Range("C2:C12"), SortOn:=xlSortOnValues, _
        Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveWorkbook.Worksheets("Sheet1").Sort
        .SetRange Range("A1:D12")
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
    
End Sub

マクロの記録から得たVBAコードは、操作時に開いていたシート名、選択したセル位置で記録されています。当然と言えば当然ですが・・・。

「このマクロコードをボタン化してシートに張り付けて・・・」という行動は全く意味がありませんので、先に言っておきます。

  •  Range(“A1″).Select は、エクセルが自動で並び替え範囲を取得したときの ” 残骸コード ” です。

本当は、CurrentRegion(カレントリージョン)のコードが付随していないと全く意味の無いコードになっています。

  •  WorkSheets(“Sheet1”) は、書いてある通りSheet1でしか機能しません。

その都度シート名を書き替えてあげないといけません。

  • Range(“A1:D12”) は、CurrentRegion(カレントリージョン)で導いた並び替え範囲です。

これでは、並び替えをしたいそれぞれのシートのデータ表のサイズが、完全一致(同行数 and 同列数)が必須の条件となってしまいます。

エクセルの機能の「並び替え」は使い回し出来ないその場だけのもの

基本、エクセルの機能の「並び替え」は使い回し出来ないその場だけのものと思ってください。

多くのエクセル利用者が一度は経験していることで、「並び替え」を失敗してデータを壊した(壊しかけた)ことがある人もいるかと思います。

「並び替え」とは単独のシート上でも、一つ設定を間違えればデータを壊す可能性のある、非常に注意の必要な操作だということです。

ですので、エクセルの機能としても、色々と制約付きでしか実行できないようにしているのだろうと思います。

それでも「シートをまたいで」並び替えを行ないたい場合

それでもシートをまたいで並び替えを便利に行いたい人は続けてお読みください。

VBA

Sub Macro並び替えtest2()
'
' Macro並び替えtest Macro
'

'

    ActiveWorkbook.ActiveSheet.Sort.SortFields.Clear
    ActiveWorkbook.ActiveSheet.Sort.SortFields _
        .Add Key:=Range("C2"), SortOn:=xlSortOnValues, _
        Order:=xlAscending, DataOption:=xlSortNormal
    With ActiveWorkbook.ActiveSheet.Sort
        .SetRange Range("A1").CurrentRegion
        .Header = xlYes
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With

End Sub

マクロの記述のコードを少し改造しました。

  •  Range(“A1”).Selectを削除
  •  WorkSheets(“Sheet1”)をActiveSheetに変更しました
  •  並び替えキーをRange(“C2:C12”)からRange(“C2”)に変更しました
  •  並ぶ替え範囲をRange(“A1:D12”)からRange(“A1”).CurrentRegionに変更しました

これで別のシートにも並び替えの対応が出来るコードになりました。

並び替え実行前
並び替え実行後

別シートでも並び替えたい範囲の違うデータ表も並び替えることが出来ました。が、・・・ことはそんなに単純ではありません。

  1.  並び替えキーは「固定」されているのでキーを変更できない
  2.  データ表が全て「A1セル」から始まるわけではない
  3.  並び替え範囲は常にひと塊(カレントリージョン)というわけではない
  4.  昇順・降順など、その都度、その他の細かい設定が出来ない
  5.  ユーザー設定の並び替えがない などなど
  6. 一番重要なのが、「ActiveSheet」とは「どのシート」で並び替えを実行しているのか?が分からない

これらの問題に対応できていないと、 結局、” 需要なデータを壊してしまう ” ことになりかねません。

並び替えマクロでシートまたぎのVBAコードを作成

最初に、実使用に耐える並び替えマクロツールを利用するにあたっては、「貴重なデータがぐちゃぐちゃ」にならないように、使い方のルールを示しておく必要があります。つまり、

元データは保存しておいて、コピーされたデータを「並び替えマクロツール」で使用すること。」を強く推奨します。

ということです。

シートを跨ぐ時に起こるかも知れない、並び替えの想定外トラブルを防止するため、その要因の防止策として重要なものは、

  •  先の並び替えで使用した「並び替え条件」を引きずらないこと。
  •  先に並び替えを行なったエクセルシートと今から並び替えを行うエクセルシートが同じか違うかを判断すること。

です。

ですので、マクロツール作成で、まず最初にこの条件対策のVBAコードを設置しておきます。

ユーザーの入力条件を代入する変数を設定

ユーザーの条件入力はユーザーフォーム「ソートナビゲーター」から行われます。

そこで入力された情報は並び替え条件として、モジュールで処理することになります。

並び替え条件は多様ですので、代入される変数も多量になります。今回それをグローバル変数として設定します。

変数名 説明
ADRange エクセルシート上の全データ量を把握(Range obj)
DataNSN、DataSN 全データ量を把握したシート、並び替えを行なうシート(string)
ErEnd PG実行中に発生したエラーによる処理中止命令(Boolean)
SSRange 並び替え範囲(Range obj)
STRCr、STRCc ユーザーが並び替え範囲内に指定したセルの行、列(Long)
KeyAddA、KeyAddB、KeyAddC ユーザーが指定した列並び替えキー(Variant)
ClrNoA、ClrNoB、ClrNoC ユーザーが指定した色並び替えキー(Variant)
RGBstyle RGB形式での色表示(String)
Rno、Gno、Bno RGB分解での各色番号(Long)
DataRange、Head ユーザーが指定した並び替えデータ範囲(String)、先頭行指定(Long)
InpAreaV ユーザーがマニュアル指定したデータ範囲(Range obj)
Stream1、Stream2、Stream3、Stream4、Stream5、Stream6 ユーザーが指定した各キーの昇順、降順(Long)
Bodu、Bodd、Bodr、Bodl ユーザーがマニュアル指定したデータ範囲の外枠罫線(Border obj)
BoduL、BoddL、BodrL、BodlL、BoduW、BoddW、BodrW、BodlW ユーザーがマニュアル指定したデータ範囲の外枠罫線の元の線種と太さ(Long)
ClrNoACellc、ClrNoBCellc、ClrNoCCellc ユーザーが指定した色並び替えキーのセル列番号(Long)
SortType ユーザーが指定した並び替えのタイプ(String)
CusOdr1、CusOdr2、CusOdr3、CusOdr1V、CusOdr2V、CusOdr3V  ユーザーが指定したユーザー設定リスト利用の可否、インポートしたユーザー設定リストの内容(String)
DCutr、DCutc、DCutEr、DCutEc データ切り出し範囲のはじめのセルと終わりのセルの行、列(Long)
DCYr ユーザーが指定したデータ切り出し行数(String)
AreaVAlert ユーザーが部分範囲指定実行時に、データ本体の列幅と部分指定の列幅が不一致の時(Boolean)
グローバル変数の宣言

モジュール(ここではModule1)の冒頭に記述します。

VBA
Option Explicit
Dim ADRange As Range
Dim DataNSN, DataSN As String
Dim ErEnd As Boolean
Dim SSRange As Range
Dim STRCr, STRCc As Long
Public KeyAddA, KeyAddB, KeyAddC As Variant
Public ClrNoA, ClrNoB, ClrNoC As Variant
Public RGBstyle As String
Dim Rno, GNo, BNo As Long
Public DataRange As String, Head As Long
Dim InpAreaV As Range
Public Stream1, Stream2, Stream3, Stream4, Stream5, Stream6 As Long
Dim Bodu, Bodd, Bodr, Bodl As Border
Dim BoduL, BoddL, BodrL, BodlL, BoduW, BoddW, BodrW, BodlW As Long
Public ClrNoACellc, ClrNoBCellc, ClrNoCCellc As Long
Public SortType As String
Public CusOdr1, CusOdr2, CusOdr3, CusOdr1V, CusOdr2V, CusOdr3V As Variant
Public DCutr, DCutc, DCutEr, DCutEc As Long
Public DCYr As String
Dim AreaVAlert As Boolean

グローバル変数の初期化をするコード

変数は、プロシージャー、マクロやプロジェクトが終了すると自動的に初期化されます。

ただし変数の種別によって初期化されるタイミングが異なります。

今回多く利用するグローバル変数は、プロシージャーが終了しても初期化されません。

(これは逆に、並び替え設定条件を保存しているという利便性にも繋がっています。)

ただし、

並び替えるシートを変更する時には、この保存機能が大きなトラブルの原因ともなりますので、一旦すべてのグローバル変数を初期化するようにします。

エクセルVBAの「Sortオブジェクト」の記述コードの中にも「並び替えの設定をクリアする」という記述を行いますが、トラブル防止のため、その「設定のクリア」の記述とは別に「変数の初期化」としてコード設計を行います。

グローバル変数の初期化

並び替え作業の実行コードの最初にこのプロシージャーを呼び出すことで無条件で変数の初期化を行います。

先の並び替えで使用した「並び替え条件」を引きずらないこと。」への対策になります。

VBA
Sub グローバル変数初期化()
    Dim ANS As Long
        If Not ADRange Is Nothing Then
            ANS = MsgBox("「並び替えデータシート全体をチェック」も" & _
                "リセットしますか?", vbYesNo + vbQuestion, "確認")
                If ANS = 7 Then
                    MsgBox "承知しました。チェックのリセット" & _
                        "は行いません。"
                Else
                    Set ADRange = Nothing
                End If
        End If
        Set SSRange = Nothing
        Set InpAreaV = Nothing
        DataSN = ""
        ErEnd = False
        STRCr = 0
        STRCc = 0
        KeyAddA = ""
        KeyAddB = ""
        KeyAddC = ""
        ClrNoA = ""
        ClrNoB = ""
        ClrNoC = ""
        RGBstyle = ""
        Rno = 0
        GNo = 0
        BNo = 0
        DataRange = ""
        Head = 0
        Stream1 = ""
        Stream2 = ""
        Stream3 = ""
        Stream4 = ""
        Stream5 = ""
        Stream6 = 0
        ClrNoACellc = 0
        ClrNoBCellc = 0
        ClrNoCCellc = 0
        SortType = ""
        CusOdr1 = ""
        CusOdr2 = ""
        CusOdr3 = ""
        CusOdr1V = ""
        CusOdr2V = ""
        CusOdr3V = ""
        DCutr = 0
        DCutc = 0
        DCutEr = 0
        DCutEc = 0
        DCYr = 0
        AreaVAlert = False
End Sub

並び替えを実施するデータシート全体の大きさを把握する

並び替えをするデータシートについて、

そのすべてのデータを並び替えたい場合もあるでしょうが、そのシートの中の一部分のデータを並び替えたい場合もあるでしょう。

そうした時には、そのデータの範囲設定場面で、確かにデータシート全体内にある(収まっている)ことを確認する必要があります。

(でないと、データシート外にある不必要なものまで巻き込んでみたり、データシートの一部分のみを不用意に並び替えてしまったりします。)

ですのでそうならないようにまず、データシートの規模を把握する必要があります。

データシート全体のボリュームを把握

このプロシージャーで、まず、このデータシートの「シート名を変数DataNSNに代入します。」

先に並び替えを行なったエクセルシートと今から並び替えを行うエクセルシートが同じか違うかを判断すること。」への対策です。(全体のボリュームを把握したシートと、並び替えしたいデータのあるシートは同じでないといけない)

全体のボリュームを把握するために、

データの始まりの行番号(多くは見出し行でしょう)、左端の開始列、右端の終了列、

行、列をクリックすることで調べます。

終端行については、データ内容によって、それぞれの列で異なることも多いですので、

全列について最終セルを調べます。その中で、最下行の行番号を取得します。これはワークシート関数のMaxで取得することが出来ます。

この4隅でデータシート全体のボリュームとします。

VBA
'データシート全体のボリュームを把握

Sub データシート把握()
    Dim ADSr, ADSc, ADEc As Range
    Dim Sr, Sc, Ec As String
    Dim SrN, ScN, EcN As Long
    Dim i As Long
    Dim ER() As Long
        ws.Select
        DataNSN = ws.Name
        On Error Resume Next
        Set ADSr = Application.InputBox("データの開始行を指定して" & _
            "ください。", Title:="データ開始行の指定", Type:=8)
        If ADSr Is Nothing Then
            MsgBox "キャンセルされました。終了します。"
            Exit Sub
        End If
        Set ADSc = Application.InputBox("データの開始列を指定して" & _
            "ください。", Title:="データ開始列の指定", Type:=8)
        If ADSc Is Nothing Then
            MsgBox "キャンセルされました。終了します。"
            Exit Sub
        End If
            Set ADEc = Application.InputBox("データの終了列を指定" & _
                "してください。", Title:="データ終了列の指定", Type:=8)
        If ADEc Is Nothing Then
            MsgBox "キャンセルされました。終了します。"
            Exit Sub
        End If
        Sr = ADSr.Address(, , xlR1C1)
        SrN = Val(Mid(Sr, 2))
        Sc = ADSc.Address(, , xlR1C1)
        ScN = Val(Mid(Sc, 2))
        Ec = ADEc.Address(, , xlR1C1)
        EcN = Val(Mid(Ec, 2))
    ReDim ER(ScN To EcN)
        For i = ScN To EcN
            ER(i) = Cells(Rows.Count, i).End(xlUp).Row
        Next i
        Set ADRange = Range(Cells(SrN, ScN), Cells(WorksheetFunction _
            .Max(ER), EcN))
End Sub

並び替え「シートまたぎ」対策VBAコードのまとめ

基本的にセルデータの並び替えは、シート毎に条件設定して、シート毎に行うようになっています。

それゆえ、エクセルの並び替え機能では、同じ操作をシート毎に行うのが通常とされています。

エクセルVBAを使って並び替えマクロツールを組み立てようとした時には、

まず前提が、並び替え条件を別シートに流用しない。並び替えを行なうシートが変わる時は、必ず条件をリセットする。

ことが必要になります。

エクセルVBAを独習するのに参考書は欠かせません。 参考書選びは自分に合った「相棒」にできるものを選んでいきたいです。

vbanarabiufcodeeyecatch UserFormに設置したコントロールのイベントコードを記述する

今回の記事はここまでです。   最後までご覧いただき有難うございました。

<記事内容についての告知>VBAコードの記述記事においては、その記述には細心の注意をしたつもりですが、掲載のVBAコードは動作を保証するものではりません。 あくまでVBAの情報の一例として掲載しています。 掲載のVBAコードのご使用は、自己責任でご判断ください。 万一データ破損等の損害が発生しても当方では責任は負いません。

アンケートでポイ活しよう!!

アンケートに答えれば答えるほど ”使える” ポイントがたまります。

NTTコム サーチ

af_banner01

Dstyle web

dstyleweb_logo
dstyle_320x50-min