[[20180514134850]] 『マクロ:全シートの同セルの同じ値の数字を転記し』(marco3) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『マクロ:全シートの同セルの同じ値の数字を転記して一覧を作成』(marco3)

ExcelのVBAを使用して、下記のようなものを作りたいと思ってます。

・シートは複数(『一覧』シート以外の全シート)を対象
・各シートの同セルの値(S1)を順番に取得し、『一覧』シートのA2から下に(A2、A3、A4…)取得した値を転記していく。
(A1は一覧表の項目名の記載有)
(このマクロを実行するにあたって、常に『一覧』シートの1行目以外は全部データは削除する仕様になっていると仮定して)

例)
シート名:Sheet1、Sheet2、Sheet3、一覧
セルS1の各シートの値:一郎、次郎、三郎

結果
「一覧」シート
A2:一郎
A3:次郎
A4:三郎

どのようなやり方が一番効率的なのか、初心者なので、ヒントをいただけると嬉しいです。
セルの値はS1以外にもありますが、やり方がわかれば、記述を増やすだけだと思ってます。

あと、その他 気を付けるべき点があれば教えていただきたいです。

よろしくお願いします。

< 使用 Excel:Excel2013、使用 OS:Windows8 >


こんにちは ^^
こんな感じでしょうか。

 Option Explicit
 Sub main()
    Dim sh01 As Worksheet
    Dim i As Long, j As Long
    Set sh01 = Worksheets("一覧")
    j = 2
    sh01.Range("A:A").ClearContents
    For i = 1 To ThisWorkbook.Worksheets.Count
        If Sheets(i).Name <> "一覧" Then
           With Sheets(i)
               sh01.Cells(j, 1) = .Cells(1, 19)
               j = j + 1
           End With
        End If
    Next
End Sub
(隠居じーさん) 2018/05/14(月) 14:42

 >どのようなやり方が一番効率的なのか
すみません。(隠居じーさん) 2018/05/14(月) 14:42は
効率的かどうかは分かりません、ただ動くだけなので。。。
(;^_^A
他の方のご回答をお待ち下さい。
シート指定には気を使ったつもりですが。。。
外していましたら、すみません。
でわ
(隠居じーさん) 2018/05/14(月) 14:58

隠居じーさん 様

ありがとうございました。
こうやってコードを見るとなるほど!と思うのですが、まだまだ全然勉強不足ですね。

ところで、私の質問の仕方が悪かったのですが、もしシート名が「sheet1」といった具合ではなく、色々なシート名があり、「一覧」シートに転記する場合はどうなるのでしょうか?

例)
シート名:A工事、あいう工事、カタカナ工事、一覧

もし、回答いただけるのであれば、よろしくお願いします。
(marco3) 2018/05/14(月) 15:09


marco3さんの疑問は、既に考慮されていますよ? シート名を変えてから動かしてみれば判るでしょう。(Sheetsとはシート名ではなく、オブジェクトです)

そして、横道に逸らしてしまう事をご容赦ください。 ご質問への直接回答ではないのですが、隠居じーさんさんのコードを見て気になった点なぞ。

1つは、ThisWorkbookを明示している箇所と省略している箇所が混在しているので、どちらかに統一すべきという点。 ThisWorkbookはデフォルトなので、省略で統一した方が、コードの文字数が少なくなって、見せたい箇所が明らかになると思うのですよ。

もうひとつは少しだけ重要ですが、WorkSheetsオブジェクトとSheetsオブジェクトは別物なのに、混在して使っている点。RangeとCellsのように、同じものを指していると理解していませんか? 調べて頂くと判ると思いますが、対象が少し違うので、番号が違う可能性があるのです。 PicturesとShapesの関係みたいなもんです。 なので、どちらかに統一すべきなのですが、現在ではほぼ同じシートを表現するので、文字数が少ないSheetsで統一するのをお薦めしておきます。
(???) 2018/05/14(月) 15:17


 こんにちは ^^
???さんが既に回答されていますが。
たくさん、シートこさえて、試して見てください。

 ???さん 、フォローありがとう御座います。
WorkSheetsオブジェクトとSheetsオブジェクト
何となく使っていましたが。とても勉強になります。
(隠居じーさん) 2018/05/14(月) 15:38

>隠居じーさん様

ありがとうございます。
ようやく、実装して確認したところ、シート名関係なく動くことが分かりました。
私の意味不明な質問でお手間お掛けしてしまって申し訳ないです。

>???様
ありがとうございます。
ちゃんと動作確認してから、質問は今後させていただきますね。
WorkSheetsオブジェクトとSheetsオブジェクト…
実はRangeとCellsの違いもきちんと理解していないので、先ほど自分で調べてみました。
奥が深くて(深すぎて)なかなか一歩二歩進めないのですが、このように皆さんが教えていただけること感謝しています。

最後に、実は今回シート数が300位になったExcelのデータを集計したくて2年間やれずじまいで、調べたけど、色々書籍読んだけど、前に進めませんでした。
たった一つの質問で先ほど、膨大なデータを一覧にすることができました。

本当にありがとうございました<(_ _)>
(marco3) 2018/05/14(月) 16:22


横から口出しになっちゃいますけど、、

>どのようなやり方が一番効率的なのか、
状況によってケースバイケースなのでなんともいえないように思います。

    Sub Sample1()
        Dim i As Long

        For i = 1 To Worksheets.Count - 1
            Worksheets("一覧").Range("A" & 1 + i).Value = Worksheets(i).Range("S1").Value
        Next i
    End Sub

    Sub Sample2()
        Dim i As Long, sh As Worksheet

        i = 1
        For Each sh In Worksheets
            If sh.Name <> "一覧" Then
                Worksheets("一覧").Cells(1 + i, "A").Value = sh.Range("S1").Value
                i = i + 1
            End If
        Next sh
    End Sub

    Sub Sample3()
        Dim i As Long, MyRNG As Range

        Set MyRNG = Worksheets("一覧").Range("A2")

        For i = 1 To Worksheets.Count
            If Worksheets(i).Name <> "一覧" Then
                Worksheets(i).Range("S1").Copy MyRNG
                Set MyRNG = MyRNG.Offset(1, 0)
            End If
        Next i
    End Sub

たとえば、一覧シートが毎回ブック最後(一番右側)にあるっていうのが前提になるのであれば、一覧シートだったら処理しないなんてことは考えずに上記のSample1のようにすればいいと思います。(必ず1番目(一番左)にあるという場合も同じ考え方ができますよね)

逆に、一覧シートの位置は不定ですというのであれば、隠居じーさんさんが示されておられるように、シート名などで処理対象か判定する必要がでてくるように思います。

>気を付けるべき点があれば
気をつけるというか、今回の処理であれば、似たような処理を繰り返していることはおわかりになりますでしょうか。
わかるのであれば、自ずと何らかの条件に基づいてループ処理をさせればよいことに気づきますよね。

そうなるとポイントとしては

(1)どうやってループを回すのか
 「Do 〜 Loop」「For 〜 Next」、「For Each 〜 Next」など

(2)コピー元から貼付先にどうやって値を持って行くか
 「値の参照:〜.Value = 〜.Value」、「COPYメソッドの実行:〜.Copy 〜」など

なんてところに注目して、自分が使いやすいのを選択していくのがいいんじゃないかなとおもいます。

ちなみに、見れば解ると思いますが、
Sample1、Sample3は「For 〜 Nextステートメント」、Sample2は「For Each 〜 Nextステートメント」でループさせています。
また、
Sample1、Sample2は、「(貼付先の)Valueプロパティに(コピー元の)Valueプロパティを参照し値を設定」していますが、Sample3では「(引数に貼付先を指定した)Copyメソッドを実行」し、コピペしています。

(もこな2) 2018/05/14(月) 18:21


 こんばんは ^^ 解決されたみたいで、よかったですね
修正版です。グラフ、ダイアログ、シート等、がもしあればセル参照がエラーになるかも?
なので。ワークシートに統一しました。
???さん 有難うございました。
 Option Explicit
Sub main()
    Dim sh01 As Worksheet
    Dim i As Long, j As Long
    Set sh01 = Worksheets("一覧")
    j = 2
    sh01.Range("A:A").ClearContents
    For i = 1 To Worksheets.Count
        If Worksheets(i).Name <> "一覧" Then
           With Worksheets(i)
               sh01.Cells(j, 1) = .Cells(1, 19)
               j = j + 1
           End With
        End If
    Next
End Sub
(隠居じーさん) 2018/05/14(月) 21:55

 >どのようなやり方が一番効率的なのか
たかが200や300のループにどれが効率的とか考える位なら、
今自分が出来る方法で一番最初に思いついた方法でやってしまったら、
いいと思います。
思い悩む時間がもったいないです。
とりあえず、書いてみて処理時間が不満ならその時高速化は考えましょう。
まずは結果を出さないと話にならないと思います。

効率的=同じことを2度書くなら変数を使う

という定義で考えると、
こんな感じですかね。。。。

Sub test()

    Dim wsResult As Worksheet
    Dim ws As Worksheet
    Dim ix As Long

    ix = 1
    Set wsResult = Worksheets("一覧")
    For Each ws In Worksheets
        If Not ws Is wsResult Then
            ix = ix + 1
            wsResult.Cells(ix, "A").Value = ws.Range("S1").Value
        End If
    Next
End Sub

どんな基準で効率的かを評価するかわかりませんが、
他の方のサンプルをみて、
「一覧」という文字列が何度も出てくるなら定数で宣言したいなと思いました。
(まっつわん) 2018/05/15(火) 13:00


>もこな2様
サンプル沢山ありがとうございます!
実は、一覧のデータ(項目)は20個位あり、値貼付けの動作ですごいコードを書き続けてました。
Sample2を見て、自分のコードを見て気が付きました。
項目を追加したり、順番を変更する度にコードの変更の手間が発生しており、これを参考にカスタマイズのできるコードに変更できそうです☆
ポイントの内容で「ループの回し方」も参考になりました。
参考書等で読んでも、実際、自分で実務としてやることに本当に意味があると思いました。
わざわざ丁寧なコメント頂きありがとうございました。

>隠居じーさん様
再度ありがとうございました。
正直、色々な方のコメント頂き、本当に参考になりました。
ちょっと出だしでパニクっての質問で横着な感じでしたが、結果色々とコメントもらったおかげで勉強になりました☆

>まっつわん様
今自分でできる方法で…
コメントありがとうございます。
実は超初心者でどのコードを使っていいのかも分かりませんでした。
やりたいことは分かってるけど、言葉にもできるけど(ある程度)、それをコードで表現することができず苦しんでます。
とはいえ、自分なりに考えて作って、そこから簡易的に落とし込んでいくことも今後大事ですね。
色々な方の貴重な意見をいただき、小さな会社で一人事務をやっている身分として、いつもこちらの皆さんのコメントや投稿を参考にさせてもらって、本当に助かってます。
変数もついつい、初めに色々と考えすぎて、先に進んでないのが現状です。
何回も書いてるなら変数…
↑まさにこれこそ、「とりあえず、やってみてから後から考えてみる」ですね。
ありがとうございました!
(marco3) 2018/05/15(火) 13:44


 >実は超初心者でどのコードを使っていいのかも分かりませんでした。 
初心者でもそうでなくても知らなければ聞けばいいのですが、
なかなか、どう聞いていいかわからないですよね。

まず、
エクセルのファイルは、
エクセルから見ると、ブックと呼びます。
で、そのブックはいくつかのシートで構成されています。
このたくさんのシートの集まり(一つでも集まり)を、
「Worksheets」
と、表現します。
そしてその中の一つのシート、例えば「一覧」というシートは、
Worksheets("一覧")
と表現します。

やりたいことは、
ブック内のシート全部を巡回して作業をしたいですよね?
こういう、集まりの中を巡回するときは、

For Each 〜 ステートメントを使用して、巡回します。

For Each ws In Worksheets
ワークシート群の中の各要素を変数wsに順番に入れていきます。というような意味になるでしょうか?
文法的に日本語にしずらいですね^^;

シート上のセル範囲もセルの集まりですので、
集まりに対してはFor Each を使うといいですが、
やりたいことによっては、使えない場合が出てくるかもしれませんので、
その辺は臨機応変に対応しましょう。
(まっつわん) 2018/05/15(火) 14:36


>まっつわん様

ありがとうございます。
丁寧で分かりやすいコメントで「そうそう!」と。

ExcelVBAの参考書なるものはたくさん買ってみたけど、こういった時にこうやりたい(こういうコードを使う)的なものが一番実用性があると思いつつ、パニックになっているのでしょうね。
皆さんの提供して頂いたコードを見ると分かるけど、それを自分が組み立てていくとなった時の部品を実は使いこなせてない(理解していない)ので、応用・流用できてないだと思います。

あまり深く考えず、完璧を求めず、面倒がらずに今後取り組んでいこうかと思いました。

色々とありがとうございました<(_ _)>
(marco3) 2018/05/15(火) 14:49


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.