[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『VBAでのソート』(こりき)
お世話になります。
毎週一回提出する資料の加工用にVBAを書いています。
肝心のソート部分がうまくいかないので質問させていただきます。
【加工対象のExcelデータについて】
1.1ブック2シートのみ(シートが増えることはありません)
2.AA列からJ列までデータあり、開始はセルA4です。1〜3行目もデータは入っていますがソートに関係ありません
3.週ごとに行数が増減します
4.4行目はタイトルで、ソートは最優先がE列昇順、次がB列昇順です。ソート条件はこの二つです
【書いたコード】
(↓これの上に他にコード書いてあります。ここまでエラーはありません)
ActiveWorkbook.Worksheets("Report").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Report").Sort.SortFields.Add Key:=Range("E5").CurrentRegion _ , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal ActiveWorkbook.Worksheets("Report").Sort.SortFields.Add Key:=Range("B5").CurrentRegion _ , SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Report").Sort .SetRange Range("A4").CurrentRegion .Header = xlYes .MatchCase = False .Orientation = xlTopToBottom .SortMethod = xlPinYin .Apply End With
【困っていること】
コードしたから2行目の.Applyでエラーが発生しています。
ネットや書籍で調べたのですが、自分では何が間違っているのかわからないので、こちらで質問させていただきます。
間違いの指摘と解決方法のご教授をよろしくお願いします。
< 使用 Excel:Excel2016、使用 OS:Windows10 >
Sub 抜粋() With ActiveWorkbook.Worksheets("Report") .Sort.SortFields.Clear .Sort.SortFields.Add Key:=.Range("E5"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal .Sort.SortFields.Add Key:=.Range("B5"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.Sort.SetRange .Range("A4").CurrentRegion .Sort.Header = xlYes .Sort.MatchCase = False .Sort.Orientation = xlTopToBottom .Sort.SortMethod = xlPinYin .Sort.Apply End With End Sub
(もこな2) 2023/01/11(水) 19:59:08
おはようございます。
お返事ありがとうございます。
.CurrentRegionのアドレスを調べる、ということですね。
このマクロを書くにあたって、週ごとに行数の増減があるので
どこからどこまでというセルの範囲指定ができないことからCurrentRegionにたどり着きまして
ネットや参考書を読んだ限りではこれでよさそうな気がしていたのですが。
.CurrentRegionのアドレスということがまだよくわかってないかもしれませんので、もう一度調べ直します。またご報告いたします。
(こりき) 2023/01/12(木) 10:25:03
おはようございます。
お返事ありがとうございます。
コードありがとうございました!
こちらで動かしてみたところ、並び替えはできましたが、2行目からソートが始まりました。
4行目以降データ範囲をソートしたいのですが、私が書いたコードもやっぱり2行目からソートされてしまって解決方法がよくわからない状況です。
シートですが、「Pivot Table」「Report」という2シートがデフォルトで抽出されまして(弊社システムのフォーマットです)、「Report」に並び替えをしたいデータが入っているのでおそらくシートの指定についてはこれで合っているのではないかと思います。
もう少し調べて、またご報告いたします。
(こりき) 2023/01/12(木) 10:32:50
お返事ありがとうございます!
Intersectというのが御座いますので
ヒントありがとうございます。
ずっとIntesectについて調べていましたが、まだよくわからないので調査継続中です。
わかり次第またご報告いたします。
(こりき) 2023/01/12(木) 12:52:36
先程はコードありがとうございました。
ところで
.Sort.SetRange .Range("A4").CurrentRegion
ですがよく見たら、「.Sort.SetRange」と「.Range("A4").CurrentRegion」の間に半角スペースがあることにきづき、これを詰めてみたところエラーが発生し、元に戻したところソートができました(ただし2行目以降ですが)
この半角スペースには何か意味があるのでしょうか。
すみませんが教えてください、よろしくお願いします。
(こりき) 2023/01/12(木) 12:53:53
Option Explicit Sub b() Dim wb, rr, lr& Set wb = ThisWorkbook With wb.Worksheets("Report") lr = .Cells(.Rows.Count, 1).End(xlUp).Row lr = IIf(lr < 4, 4, lr) If lr < 5 Then Exit Sub Set rr = Intersect(.Range("A4").CurrentRegion, .Range(.Rows(4), .Rows(lr))) With .Sort .SortFields.Clear .SortFields.Add Range("E5") .SortFields.Add Range("B5") .SetRange rr .Header = xlYes .Apply End With End With End Sub こんな感じでせうか。。。^^; m(__)m (隠居Z) 2023/01/12(木) 16:22:32
Sub 抜粋() With ActiveWorkbook.Worksheets("Report") .Sort.SortFields.Clear .Sort.SortFields.Add Key:=ActiveSheet.Range("E5"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal '★ActiveSheetに依存 .Sort.SortFields.Add Key:=ActiveSheet.Range("B5"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal '★ActiveSheetに依存 .Sort.SetRange ActiveSheet.Range("A4").CurrentRegion '★ActiveSheetに依存 .Sort.Header = xlYes .Sort.MatchCase = False .Sort.Orientation = xlTopToBottom .Sort.SortMethod = xlPinYin .Sort.Apply End With End Sub
すわなち「ActiveWorkbook.Worksheets("Report")」と「ActiveSheet」が同じシートを示しているのですか?というのが私のコメントの趣旨です。
■2
>4行目以降データ範囲をソートしたい
既にアドバイスを受けていますが、「.Range("A4").CurrentRegion」がどのセル範囲を示しているのか手作業で確認されてみてはどうですか?
もしくは、難しく考えずに4〜適当な行までを範囲にするとか・・・
Sub 抜粋() With ActiveWorkbook.Worksheets("Report") .Sort.SortFields.Clear .Sort.SortFields.Add Key:=.Range("E5"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal .Sort.SortFields.Add Key:=.Range("B5"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal .Sort.SetRange .Range("A4:E10000") '★ここを必要であろう行までにする .Sort.Header = xlYes .Sort.MatchCase = False .Sort.Orientation = xlTopToBottom .Sort.SortMethod = xlPinYin .Sort.Apply End With End Sub
(もこな2) 2023/01/12(木) 17:55:45
おはようございます。
昨日はあれから上司に別途急ぎの用件を依頼されたものでVBAは一旦保留となってしまいました。
お返事ありがとうございました。
>>この半角スペースには何か意味があるのでしょうか。
>メソッドの引数だと思いますよ。
>ご自分で、パラメーターを持つプロシジャーを作成して見れば
>なぁ〜ンとなく解かるのではないでせうか。
とのこと、教えていただきありがとうございます。
まだ学習中なのでもっと調べてみます。
さて、コードありがとうございました!
実行してみたところ
With wb.Worksheets("Report")
ここで「実行時エラー9 インデックスが有効範囲にありません」が出ました。
確認したのですがワークシート名はこれで間違いないので何が引っかかっているのか謎です。
やりたいことだけ調べてもなかなか答えは出ないものですね。
先はまだ(本当に)長そうですが、学習を継続していきます。
(こりき) 2023/01/13(金) 10:52:55
おはようございます。
細かいご説明ありがとうございます。
昨日は途中で急ぎの用件を頼まれてしまい、こちらにまで手が回らなくなってしまいました。
ご質問の件ですが、
■1
>すわなち「ActiveWorkbook.Worksheets("Report")」と「ActiveSheet」が同じシートを示しているのですか?というのが私のコメントの趣旨です。
はい、さようでございます。
このブックにはワークシートが2枚しかなく(DBシステムから抽出しています)、1枚は「Pivot Table」でもう1枚が「Report」です。「Pivot Table」は使う必要が全くないので削除していいと思うのですが、前任者から引き継いだ時そのままなので同じようにしています(削除していいような気がしてきました)。
■2
>4行目以降データ範囲をソートしたい
既にアドバイスを受けていますが、「.Range("A4").CurrentRegion」がどのセル範囲を示しているのか手作業で確認されてみてはどうですか?
手作業で確認というのは、隠居ZさんのIntersectメソッドのことですよね?
これがまたわからなくて昨日ずっと調べていました(まだわからずじまいです)。
さてコードのご提案ありがとうございました。
上記書いてくださった、行指定を1000までにして動かしたら理想の形になりました!
今のところ1000行までは増えないのでひとまずこちらを採用して運用させていただきます。
初心者ながら、最終行を自動取得するようなコードの方がスマートな書き方かなと思っていましたがまだそんな生意気なことはできませんね。
いろいろご教授いただきましてありがとうございました。
(こりき) 2023/01/13(金) 11:11:08
実は前任者から引き継いだマクロがあったのですが(作成者はまた別のスタッフ)それがある日動かくなりまして、そのメンテナンスもかなり面倒臭かったので諸々簡略化して自分で書くことにしたのです。
動かなくなったマクロはかなり複雑で標準モジュールと、Functionとやらがありこれを改造するのは至難の業なので1から自分で書き直してみました。
Excelの通常のソートは簡単なのにコードでソートを書くのがこんなに大変だとは思ってもみませんでした。
ただ、わからなかったことが少しずつわかってくると楽しいですね。
コメントをお寄せくださり、ありがとうございました。
(こりき) 2023/01/13(金) 11:14:18
>>>この半角スペースには何か意味があるのでしょうか。 >>メソッドの引数だと思いますよ。 >>ご自分で、パラメーターを持つプロシジャーを作成して見れば >>なぁ〜ンとなく解かるのではないでせうか。 >とのこと、教えていただきありがとうございます。 >まだ学習中なのでもっと調べてみます。
半角スペースが引数の訳ないでしょっ。(書き方の問題だとは思いますが)
.Sort.SetRangeメソッドに引数を与える為に、区切りとしてスペースを入れただけです。
こう書くのと同じことです。(Callを省略した時は、引数を囲っていたカッコも省略するので、上の書き方になります) ↓ Call .Sort.SetRange(.Range("A4").CurrentRegion)
(半平太) 2023/01/13(金) 11:41:49
おはようございます
コメントありがとうございます。
今Callステートメント調べました、半角スぺ^スの意味が分かりました。
ありがとうございました。
(こりき) 2023/01/13(金) 12:06:09
おはようございます。
質問ですが、上記書いてくださったコードの変数で
>Dim wb, rr, lr&
wbはworkbookだと思いますがrr, lr&は何を指しているのでしょうか。
お手数をおかけしますが教えてください、よろしくお願いします。
(こりき) 2023/01/13(金) 12:09:22
>>Dim wb, rr, lr& ←手抜き工事です済みません
wb バリアント型
rr バリアント型
lr Long型
を略式で宣言しています。
Dim wb As Workbook
Dim rr As Range
Dim lr As Long
と書くべきでした。m(__)m
詳細は
VBA 変数の型。等々でご検索を。m(__)m
^^;
m(__)m
(隠居Z) 2023/01/13(金) 12:16:37
お返事ありがとうございます。
半角スペースについての説明文をちょうど読み終えたところです(ググってみました)。
こちらこそわからないことだらけで、説明をして下さる皆様にもどかしい思いをさせてしまって申し訳ありません。
変数についてもご説明ありがとうございました。
本当にこんな初歩的なことからまだわかってなかったのかとつくづく思いしりました。
お手数をおかけいたしました、ありがとうございます。
(こりき) 2023/01/13(金) 12:37:45
>>With wb.Worksheets("Report")
>>ここで「実行時エラー9 インデックスが有効範囲にありません」が出ました。
こちらまだでございます。すみません。
質問をする→お返事をいただく→その内容をググって調べる(知らないことが多い)
のループをしてましてまだこちらまでたどり着いておりませんでした。
>私のコードではマクロが書かれているブックを格納していますので
>処理対象のブックがその他のブックでしたらエラーになると思います。
承知いたしました!同じ条件でもう一度試してみようと思います。
結果が出ましたらまたご報告させていただきます。
(こりき) 2023/01/13(金) 12:41:11
できたー!!
できました!!
先程のコードを加工するブックにに格納したところ、エラーも出ず並び替え完成いたしました。
求めていたシートが出来上がりました!
毎週金曜日に新しくデータを抽出するため、出来ればマクロは別ブックで保存しておきたいのであともう少し調べて理想の結果にできるようにします。
隠居Z様、もこな2様からご提案いただいたコードと
自分が書いたコードを比較して何が間違っていたかの検証もします。
こちらで質問してよかったです。
ありがとうございました。
(こりき) 2023/01/13(金) 12:50:53
■3
>はい、さようでございます。
誤解されているかもしれないので、ちょっと補足。
【標準モジュール】シートの指定を省略した場合は、ActiveSheetを指定したものとして扱われるというお話をしました。
では【シートモジュール】でシートの指定を省略した場合はどうなるかというと、そのシートを指定したものとして扱われます。
したがって、↓の場合に「ActiveWorkbook.Worksheets("Report")」と「指定が省略されたシート」が一致しなくなります
【標準モジュール】に記述している場合であって、「Pivot Table」シートがアクティブである場合 【シートモジュール】に記述している場合
よって「「Pivot Table」は使う必要が全くないので削除していいと思う」とのことですが、そういった解決法よりきちんと(ブックや)シートを指定することを考えた方が確実でしょう。
■4−1
>手作業で確認というのは、隠居ZさんのIntersectメソッドのことですよね?
まったく違います。
元のコードでは↓のようになっていたわけです。(標準モジュールに書いてあったとして説明してます)
ActiveSheet.Range("A4").CurrentRegion
すなわち↓で選択されるセル範囲を確認してみては?という意味です。
(1) A4セルを選択する (2) キーボードの「Ctrl」と「*」を同時押しする
おそらく2〜3行目も表範囲として認識されているのでしょう。
■4−2
Intersectメソッドについてはちゃんと調べてみましたか?
セル(範囲)が重なった部分を取り出す命令なわけですから、例えば↓のようにすれば4行目以降になるでしょうとアドバイスを受けています。
Sub 実験() Worksheets.Add Range("A4:E10").Value = "★" Range("B2,C3").Value = "♪"
MsgBox _ "Range(""A4"").CurrentRegion" & vbLf & " " & _ Range("A4").CurrentRegion.Address(False, False) & " ←2行目からになる" & vbLf & vbLf & _ "Intersect(Range(""A4"").CurrentRegion,.Rows(""4:"" & Rows.Count))" & vbLf & " " & _ Intersect(Range("A4").CurrentRegion, Rows("4:" & Rows.Count)).Address(False, False) & " ←4行目からになる" End Sub
(もこな2) 2023/01/13(金) 12:59:11
こんにちは。
コメントありがとうございます。
■3
>誤解されているかもしれないので、ちょっと補足。
【シートモジュール】を使ったことがなかったのでこれがどういうものか調べてました。
念のため作ってあるマクロのシートモジュールを見ましたが何も書いていませんでした。
(、と、このお返事も果たして理解したうえで書けているか不安なのですが)
>よって「「Pivot Table」は使う必要が全くないので削除していいと思う」とのことですが、そういった解決法よりきちんと(ブックや)シートを指定することを考えた方が確実でしょう。
ご指摘ありがとうございます。
あまり短絡的に考えないようにします。
■4−1
>元のコードでは↓のようになっていたわけです。(標準モジュールに書いてあったとして説明してます)←はい、そうです。
>ActiveSheet.Range("A4").CurrentRegion
>すなわち↓で選択されるセル範囲を確認してみては?という意味です。
>(1) A4セルを選択する
>(2) キーボードの「Ctrl」と「*」を同時押しする
>おそらく2〜3行目も表範囲として認識されているのでしょう。
そういうことだったのですね、理解しておらず失礼いたしました。
今確認したところ1行目から最終行までデータが入っているセルが全選択されました。
■4−2
>Intersectメソッドについてはちゃんと調べてみましたか?
こちらについてはまだ手が回ってないのでこれから調べます。
書籍とネットの情報は読みましたが、まだ自分で試しコードを書いたり出来てないのです。
すみません。
調べてそれを理解するまでにどうしても時間がかかってしまいまして、すぐお返事ができずに申し訳ありません。
(こりき) 2023/01/13(金) 15:44:21
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.