Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


238 / 3841 ページ ←次へ | 前へ→

【77681】Re:VBAを使い、別シートにデータを抽出し...
発言  β  - 15/11/28(土) 13:48 -

引用なし
パスワード
   ▼たけちゃんまん さん

コードの解説(といってもそんなにたいそうなコードではないのですが)は以下の通りですが
その前に、是非、エクセルの強力な機能であるオートフィルターやフィルターオプションを
シート上の操作で体験して、その便利さを実感してください。
オートフィルターについてはおそらく、経験があるとは思いますが、「オートフィルター」
あるいは「フィルターオプション」で検索して、出てくるページの中でわかりやすいものを参考に
実際にやってみてください。
いずれも、処理効率も、ゴリゴリコードを書いて処理するより、格段に優れています。

フィルターオプションはオートフィルターに比べて、与える条件も細かに設定できますし
また、その場所でフィルタリングの他にフィルタリング結果を別の場所に抽出ということも
その標準機能の中で実現可能で、優れものです。
ただ、条件の設定がちょっと煩雑(?)で、最初は敬遠されがちかも。

いずれにしても、これら操作をマクロ記録しますと、私がアップしたコードが生成されます。

なお、オートフィルターでxl2007以降限定と書きましたが、オートフィルター自体は古くからある機能。
ただ、xl2003までは、抽出対象を2つまでしか与えられなかったのですが、xl2007以降、必要なだけ
与えることができるようになっています。

'フィルターオプション
  
  Application.ScreenUpdating = False

   '処理中の画面の動きを隠します。画面のちらつきを抑止するとともに、
   'セル書き込み時の処理効率をアップさせる効果があります。
  
  Set shT = Sheets("Sheet2") '転記シート

   'コード内で何度か参照しますので、短めの名前の変数に代入して
  '以降は shT を使います。コードが見やすくなる効果があります。

   shT.UsedRange.ClearContents
  
   'UsedRange は、そのシートで使用されている領域を矩形で表したアドレス領域。
   'これから、そのシートに転記するので、その前に、クリアしておきます。

  With Sheets("Sheet1")    '元シート

   '↑で shT に代入するコードがありましたが、もう1つ、オブジェクトを With でくくって
  '以下、End With までの間でそのオブジェクトを参照する場合、.そのオブジェクト という
   '記述ができます。これも、コードを見やすく、すっきりさせる効果があります。

    cols = .UsedRange.Columns.Count

   'UsedRange は使用領域。Sheet1 は A列 から始まっていますので、その列数が転記列数になります。

    Set r = .Range("A1", .UsedRange).Offset(1)

   'Sheet1 のタイトル行は2行目です。わかりにくいかもしれませんが
   '.Range("A1", .UsedRange) は、2行目から始まるリストの領域に1行目を加えた領域になります。
   'で、.Offset(1) は、それを1行下に移動させたところ、つまりリスト領域に、その下の空白行を
   '加えた領域になります。本来、この空白行は不要ですが面倒なので、リスト領域に含めています。
   '1行目が完全に空白行であれば .UsedRange.Offset(1) でいいのですが、そこが不明でしたので
  'あえて このような書き方にしました。

    .Cells(1, cols + 2).Value = .Range("I2").Value '抽出項目タイトル

   'フィルターオプションに与える抽出条件項目名を、リスト領域の外につくります。

    .Cells(2, cols + 2).Resize(3).Value = WorksheetFunction.Transpose(Array("'=b001", "'=b002", "'=b003"))

   'その下、2行目以降に抽出文字列を3つセットしています。たんに b001 といった文字列にしますと
   'b001 からはじまるものすべてが対象になりますので = を付けて完全一致条件にしています。

    r.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Cells(1, cols + 2).CurrentRegion, _
                CopyToRange:=shT.Range("A1"), Unique:=False

   'この1行がフィルターオプション実行コードです。抽出結果を SHeet2のA1から始まる領域に転記します。

    .Cells(1, cols + 2).CurrentRegion.Clear

   '処理後、リスト領域の外側に作った条件欄をクリアします。

  shT.Select

   '処理結果が目で見れるように最後に Sheet2をアクティブにします。
  
'オートフィルター

  ★フィルターオプションで説明したコードについては割愛します。

    .AutoFilterMode = False

   '念のため、オートフィルターモードを解除します。

    r.AutoFilter Field:=9, Criteria1:=Array("b001", "b002", "b003"), Operator:=xlFilterValues

   'この1行で、リストのI列に指定の文字列があるものをフィルタリングします。

    If r.Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then r.Copy shT.Range("A1")

   '抽出があった場合、タイトル行以外にデータ行がありますので、その状態かどうかを判定し
  '抽出されていれば、オートフィルター領域を Sheet2の A1から始まる場所にコピペします。
   'ここが、オートフィルターの「ミソ」なんですが、抽出されたものだけがコピペ対象になります。

    .AutoFilterMode = False

   '処理後、オートフィルターモードを解除します。
・ツリー全体表示

【77680】Re:VBAを使い、別シートにデータを抽出し...
お礼  たけちゃんまん  - 15/11/28(土) 0:48 -

引用なし
パスワード
   βさま

フィルターオプション並びにオートフィルターについてのお礼が一つになってしまい、申し訳ありません。

excel2010を使用しておりますので、オートフィルターも実行させて頂きます!
・ツリー全体表示

【77679】Re:VBAを使い、別シートにデータを抽出し...
お礼  たけちゃんまん  - 15/11/28(土) 0:32 -

引用なし
パスワード
   βさま

迅速にご対応頂き、ありがとうございます!
早速、実行してみたいところではあるのですが、会社PCの会社サーバーでの作業となる為、すぐに結果のご報告が出来ず、申し訳ありません…。
月曜日にフィルターオプション及びオートフィルターの双方を実行させて頂き、結果をご報告させて頂きますので、お時間を頂けますでしょうか。宜しくお願い致します。

βさまにお伺いするのは厚かましいのは承知の上で、一つお願いがございます。

それぞれのコードがどの様な働きをしているのか、ご教授頂きたいのですが…。今回、ご教授頂いたコードについて学習し、これから先の作業に活かせる様にしたいと思っておりますので、宜しくお願い致します。
・ツリー全体表示

【77678】Re:VBAを使い、別シートにデータを抽出し...
発言  β  - 15/11/28(土) 0:06 -

引用なし
パスワード
   ▼たけちゃんまん さん

オートフィルター版も。
ただし、xl2007以降限定。

Sub Sample2()  'オートフィルター
  Dim cols As Long
  Dim r As Range
  Dim shT As Worksheet
 
  Application.ScreenUpdating = False
 
  Set shT = Sheets("Sheet2") '転記シート
  shT.UsedRange.ClearContents
 
  With Sheets("Sheet1")    '元シート
    cols = .UsedRange.Columns.Count
    Set r = .Range("A1", .UsedRange).Offset(1)
    .AutoFilterMode = False
    r.AutoFilter Field:=9, Criteria1:=Array("b001", "b002", "b003"), Operator:=xlFilterValues
    If r.Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then r.Copy shT.Range("A1")
    .AutoFilterMode = False
  End With
 
  shT.Select
 
End Sub
・ツリー全体表示

【77677】Re:VBAを使い、別シートにデータを抽出し...
発言  β  - 15/11/27(金) 23:49 -

引用なし
パスワード
   ▼たけちゃんまん さん

フィルターオプションやオートフィルター処理が適していると思います。
以下はフィルターオプション。
元シート名や転記先シート名は実際のものに変更してください。

Sub Sample()  'フィルターオプション
  Dim cols As Long
  Dim r As Range
  Dim shT As Worksheet
  
  Application.ScreenUpdating = False
  
  Set shT = Sheets("Sheet2") '転記シート
  shT.UsedRange.ClearContents
  
  With Sheets("Sheet1")    '元シート
    cols = .UsedRange.Columns.Count
    Set r = .Range("A1", .UsedRange).Offset(1)
    .Cells(1, cols + 2).Value = .Range("I2").Value '抽出項目タイトル
    .Cells(2, cols + 2).Resize(3).Value = WorksheetFunction.Transpose(Array("'=b001", "'=b002", "'=b003"))
    r.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Cells(1, cols + 2).CurrentRegion, _
                CopyToRange:=shT.Range("A1"), Unique:=False
    .Cells(1, cols + 2).CurrentRegion.Clear
  End With
  
  shT.Select
  
End Sub
・ツリー全体表示

【77676】VBAを使い、別シートにデータを抽出したい
質問  たけちゃんまん  - 15/11/27(金) 23:22 -

引用なし
パスワード
   はじめて投稿させて頂きます。
VBAの知識はほぼ無いに等しいのですが、本やサイトで検索し、自分なりに考え、昨日から色々と試していますが、エラーとなるか、正しく反映されません。

<目的>
5000行程でA〜AB列まで入力されているのデータベースがあります。データは日々、20行程追加します。
そのデータベースの商品コードと一致するデータを行ごと別シートに抽出したいです。

<データベースの列構成>
A/B/C/D/…/I/J/K/L/M/…
処理状況/メモ/番号/日付/…/商品コード/商品名/規格/数量/単位/…
済/(空白)/0001/11月1日/…/a001/みかん/大/100/個/…
(空白)/(空白)/0002/11月1日/…/b001/りんご/小/20/個/…
(空白)/(空白)/0003/11月1日/…/c001/もも/大/10/個/…
済/(空白)/0004/11月2日/…/b002/りんご/大/15/個/…
(空白)/(空白)/0005/11月2日/…/b001/りんご/小/20/個/…
(空白)/(空白)/0006/11月3日/…/b003/りんご/中/50/個/…
済/(空白)/0007/11月4日/…/a001/みかん/大/80/個/…
済/(空白)/0008/11月4日/…/a002/みかん/中/30/個/…
この様なデータを日々追加します。
※2行目がタイトルで、3行目以降が上記データとなります。

このデータの中から、I列の商品コードがb001とb002とb003の行だけを別シートに表示したいです。

ご教授頂けます様、宜しくお願い致します。



・ツリー全体表示

【77674】お願いします
質問  arusu  - 15/11/26(木) 11:13 -

引用なし
パスワード
   以前にこの質問をしたのですが、追加で回答お願いします。

例えばセルのA1に計算式があって、そこの答えが5〜9になるまで計算を繰り返すというものを組みたいです。

A1の計算式にはB1とC1の足し算だとしてB1、C1にはRANDBETWEEN()を使い、ランダムに数字がくるようにします。

なので5〜9の間に計算結果が入ったら、その答えをA1に。
もしそれ以外の数値だったら再計算させて、5〜9になるまでし、Aには5〜9までの数字が入るようにしたいです。

、もうひとつ条件を加えたい場合、
例えばA1の5〜9までの条件かつ、A2には6〜10までの数字がくるまで再計算させる方法を知りたいです。
よろしくお願いします。
・ツリー全体表示

【77673】Re:シート内のリンクについて
お礼    - 15/11/25(水) 18:01 -

引用なし
パスワード
   ▼独覚 さん:

うまく行きました!
有難うございましたm(_ _)m
・ツリー全体表示

【77672】Re:オートフィルターについて
お礼    - 15/11/21(土) 17:30 -

引用なし
パスワード
   ▼β さん:
素晴らしいです。
大変助かります。
出社後、即試してみます!

γさんと同様に
どこに原因があるか、教えて下さって
また、解決法も教えていただき、
有難うございました。

ここを訪れて良かったです。
・ツリー全体表示

【77671】Re:オートフィルターについて
お礼    - 15/11/21(土) 17:28 -

引用なし
パスワード
   ▼γ さん:
有難うございます。
出社後、即試してみます!
どこに原因があるか、教えて下さって
また、解決法も教えていただき、
有難うございました。
・ツリー全体表示

【77670】Re:オートフィルターについて
発言  β  - 15/11/21(土) 9:39 -

引用なし
パスワード
   ▼古 さん:

以下は参考コードとして。

SHeet1でオートフィルターをかけて、抽出があった場合、抽出されたものだけをSHeet2にコピーしています。
(抽出がなかった場合にこれを行うと全件コピーされるので、抽出有無をチェックしています)


Sub Test()
  With Sheets("Sheet1")
    .AutoFilterMode = False '念のため解除
    .Range("A8").AutoFilter '再設定
    .AutoFilter.Range.AutoFilter Field:=9, Criteria1:="<>4"
    '実際に抽出があった場合のみ
    If .AutoFilter.Range.Columns(1).SpecialCells(xlCellTypeVisible).Count > 1 Then
      'オートフィルター領域をコピペすると、抽出部分だけがコピーされる。
      .AutoFilter.Range.Copy Sheets("Sheet2").Range("A8")
    End If
  End With
End Sub
・ツリー全体表示

【77669】Re:オートフィルターについて
発言  γ  - 15/11/21(土) 9:22 -

引用なし
パスワード
   横から失礼。

Selection.SpecialCells(xlCellTypeVisible).Select
が、表示されている、つまり可視データに限定する意図だと思いますが、
そこはどう考えていますか?

もっとも、
可視セルにあえて限定しなくても、
フィルタが掛かったセル範囲をそのままコピペイストすると、
Excel側が気を利かせて、可視セルだけを対象に絞ってくれます。
ですから、↓のような書き方で上手くいくはずです。

Worksheets("抽出").AutoFilter.Range.Copy Worksheets("集約").Range("A1")

なお、貼付先に前の作業の結果が残っていると、その上に上書きされますが、
貼付前に、一旦消去しておくと、誤解が生じないでしょう。
そのあたりにも気を配ってください。
・ツリー全体表示

【77668】Re:オートフィルターについて
質問    - 15/11/21(土) 8:18 -

引用なし
パスワード
   ▼γさん、β さん:

お陰様で、原因が分かりました!
なんてバカなんでしょう。
ボタンで一連のマクロを実行していたので操作を忘れていました・・・

I列を”4を含まない”にフィルターで絞った後、
  Range(Selection, Selection.End(xlToRight)).Select
  Range(Selection, Selection.End(xlDown)).Select
  Range(Selection, Selection.End(xlDown)).Select
  Selection.SpecialCells(xlCellTypeVisible).Select
  Selection.Copy

絞ったデータをもう一つのシート(”集約”シート)にコピーしていました。

なので、フィルターに原因があるわけでなく、コピペが原因だったようです。
非表示の分までペーストされていたようです。

調子が良くて申し訳ないですが、質問を変えます。
絞ったデータのみコピペするには、
どう修正すれば良いでしょうか!!
申し訳ありません!
・ツリー全体表示

【77667】Re:オートフィルターについて
お礼    - 15/11/20(金) 23:42 -

引用なし
パスワード
   ▼β さん:
お返事有難うございます。
よくよく自分で見てみると、A1032セルを選択する必要は
ありませんでした。(マクロ記録した時は1032行までデータがあったみたいです)
さらに
  Range(Selection, Selection.End(xlToRight)).Select
  Range(Selection, Selection.End(xlDown)).Select
  Range(Selection, Selection.End(xlDown)).Select
で、データ全体を選択してもいますが、この必要はなかったですね。
この全体のデータの中で、I列が”4ではないもの”を抽出したいだけなのに
私は何をしているのでしょう。。。(マクロの記録時に、色々とやってしまったようです。お恥ずかしい限りです)


>もう1つ、どこかのシートの内容を抽出シートにコピペして、そこでオートフィルターで抽出ですね。
>もしかして、元データから抽出した結果を、抽出シートに転記したいということではないのですか?

その通りです。全データSheetがあり、その内容を抽出シートにコピペします。
抽出シート上でI列で”4ではないもの”を抽出します。
全データSheetは、外部からのリンクが複雑に絡んでいるため、直にいじらない方が
良いと思い、抽出シートにコピペしています。


>また、元データのレイアウト、特に 7行目がどうなっているのか、それを説明いただけると
>より具体的に検討することができるかと。

有難うございます。
なので、元データと抽出シートのレイアウトは全く同じです。
7行目はブランクです。
8行目は項目名が入っています。

謎なのは、マクロの記録で”4を含まない”にしたらCriteria1:="=4"と
なったこと。また、それでも4が時々混在することです。
質問文にも書いていますが、
Selection.AutoFilter Field:=9, Criteria1:="<>4"
に修正したら、4のものが大量に抽出されたことです。
もう意味が分かりません。

データの書式が揃っていないのでしょうか・・・
・ツリー全体表示

【77666】Re:コンボボックスへのデータ設定
発言  める  - 15/11/20(金) 20:20 -

引用なし
パスワード
   >Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2)).Value
>です。

Worksheets(myWsn).Range(Worksheets(myWsn).Cells(MinRow, 2 _
), Worksheets(myWsn).Cells(MaxRow, 2)).Value

としたほうがよいかと思います。(あえてWithは使ってません)
・ツリー全体表示

【77665】Re:オートフィルターについて
発言  β  - 15/11/20(金) 9:01 -

引用なし
パスワード
   ▼古 さん:

γさんも指摘しておられますが、「選択」して、何をしたいのか、その目的を説明されれば
その目的に合致したより良い処理案も提示できるかもしれません。

もう1つ、どこかのシートの内容を抽出シートにコピペして、そこでオートフィルターで抽出ですね。
もしかして、元データから抽出した結果を、抽出シートに転記したいということではないのですか?

また、元データのレイアウト、特に 7行目がどうなっているのか、それを説明いただけると
より具体的に検討することができるかと。
・ツリー全体表示

【77664】Re:コンボボックスへのデータ設定
お礼  goro  - 15/11/19(木) 11:09 -

引用なし
パスワード
   ▼β さん:
>▼goro さん:
>
>まず、アプリケーション定義エラーは領域規定としての
>
>Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2).Value)
>
>これは間違いです。
>
>領域としては
>
>Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2))
>
>ですし、その値ということなら
>
>Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2)).Value
>
>です。
>
>次に、重要なことですが、AddItemメソッドは、リストに対して、項目を
>【1つずつ】追加するメソッドです。領域の値をどさっと追加することはできません。
>
>アップされた例なら
>
>Sheets(myWsn).OLEObjects("ComboBox" & CmbNo).Object.List = Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2)).Value
>
>ですね。

β さん

回答頂き、ありがとうございました。
うまくいきました。

ネットでいろいろ調べていましたが、理解があやふやだったようです。
・ツリー全体表示

【77663】Re:コンボボックスへのデータ設定
発言  β  - 15/11/19(木) 10:52 -

引用なし
パスワード
   ▼goro さん:

まず、アプリケーション定義エラーは領域規定としての

Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2).Value)

これは間違いです。

領域としては

Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2))

ですし、その値ということなら

Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2)).Value

です。

次に、重要なことですが、AddItemメソッドは、リストに対して、項目を
【1つずつ】追加するメソッドです。領域の値をどさっと追加することはできません。

アップされた例なら

Sheets(myWsn).OLEObjects("ComboBox" & CmbNo).Object.List = Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2)).Value

ですね。
・ツリー全体表示

【77662】コンボボックスへのデータ設定
質問  goro  - 15/11/19(木) 10:02 -

引用なし
パスワード
   こちらは何度か利用させて頂いてます。

さて、複数のコンボボックスに対して、ワークシート上に入力してあるデータを
選択肢に設定したいと思っています。
それぞれのコンボボックスについて、データが入力されている範囲が異なるので、
「Cells(MinRow, 2), Cells(MaxRow, 2)」の様に変数で指定しています。

が、「アプリケーション定義またはオブジェクト定義のエラー」となります。
色々調べましたが、どこが悪いのかわかりません。

済みませんが、教えてください。

Worksheets(myWsn).OLEObjects("ComboBox" & CmbNo).Object.AddItem Worksheets(myWsn).Range(Cells(MinRow, 2), Cells(MaxRow, 2).Value)
・ツリー全体表示

【77661】Re:オートフィルターについて
お礼    - 15/11/18(水) 22:51 -

引用なし
パスワード
   ▼γ さん:早速のご回答有難うございます!

休暇を取ってしまったので
出社したら、すぐに試そうと思います。

取り急ぎ、お礼まで。
・ツリー全体表示

238 / 3841 ページ ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free