- ベストアンサー
VBAで複数列に対する処理方法
- VBAを使用して離れた複数の列に対して処理を行う方法を教えてください。
- 具体的には、任意の列を全選択し、その中の一部の行に対してセル結合解除を行いたいです。
- 現在、1列だけの場合は処理ができるのですが、複数列に対して処理を行う方法がわかりません。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
個別の範囲なら処理できる、しかし複数の選択範囲を個別の範囲にバラす方法が分からない、というのが質問の核のようなので…。 Excel VBAのヘルプでRangeオブジェクトのプロパティを見ていくと、Areasというのがあります。 これでインデックスを指定して個別に参照できます。 Sub aaaa() Dim i As Integer Dim r As Range '列を参照する For i = 1 To Selection.Areas.Count Set r = Selection.Areas(i) '列ごとの処理を実施 MsgBox r.Address & " -> " & r.Rows("3:5").Address Next End Sub
その他の回答 (5)
- mitarashi
- ベストアンサー率59% (574/965)
ちょっと横からおじゃまさせていただきます。 オブジェクト変数を使わずに、たとえば Range("$A:$A,$D:$E") から、スマートに単独の列をとりだす方法は思いつきませんので、オブジェクト変数を用います。 Sub test1() Dim targetRange As Range, myArea As Range, myColumn As Range '一旦、オブジェクト変数に受けると、インテリセンスが効いて 'Rangeオブジェクトの様々なメンバが表示されるので、参考になります Set targetRange = Selection 'Range("$A:$A,$D:$E")の様な場合に対応するため、下記が常道 For Each myArea In targetRange.Areas For Each myColumn In myArea.Columns Debug.Print myColumn.Address Next myColumn Next myArea '下記でも結果は同じでした ' For Each myColumn In targetRange.Columns ' Debug.Print myColumn.Address ' Next myColumn 'しかし 'Debug.Print targetRange.Columns.Count 'は最初の群の列数1を戻し、総列数の3は戻しません End Sub さて、本題に戻って、 Sub test2() Dim myColumn As Range For Each myColumn In Selection.Columns '一列に対する処理を記述 Next End Sub とすれば良いですが、ご質問の文中のロジックでは、一列に対する処理の方も動かないと思います。 intIX_1 = intIX_1 + 1 では、次の結合セルに移りません。次の行に行くだけです。 intIX_1 = intIX_1 + 当該結合セルの行数(Range(...).MergeArea.Rows.Count) にしなければいけませんね。 (他にOffset(1,0)で移る方法もあります) ご参考まで。
お礼
ご回答ありがとうございます。For Eachを使ってもやり様があるのですね。勉強になりました。 あと質問文にあるintIX_1 = intIX_1 + 1 は行変更のために使ってたものなのは間違いないですし、これだと選択した他の列に移動できないのも分かってました(なので離れた列にも処理を行うには?と質問を投げました)。それは大丈夫です。ただ「intIX_1 = intIX_1 + 当該結合セルの行数(Range(...).MergeArea.Rows.Count)」の部分はとても勉強になりました。ありがとうございました。
- 0909union
- ベストアンサー率39% (325/818)
大事な事忘れていました。 よく素人の方だと、バージョンをまったく無視して作る方が多いです。それで、何でできないのかと、よくここで質問されます。 何のバージョンのエクセルを対象にしているか、記載しましょう。もっともちゃんと理解しているなら、最初からバージョンの記載はあるはずですが また、COMからのアクセスは、そのプラットフォームに依存するので、例えばコレクションや引数の指定などは、できない場合もあります。それはマイクロソフトのMSDNのサイトにテクニカル情報として、どうすればいいいか記載があります。 と言うことは、COMで使用している場合は、呼び出し元も記載しないと、明確にできるとかできないとか言い切れるものではありません。
お礼
No3とNo4の回答について、まとめてこっちでお礼をします。回答ありがとうございます。 書き方が悪かったので訂正します。Range("E:E","G:G").SelectをRange("E1:E5","G1:G5").Selectにするのは無理ですよね?と聞いたのは、実際試してみて駄目だったんで書きました。考え方を変えて、最初からE1:E5とG1:G5のセルを選択するようにしてみようと思いましたが、離れた「任意の」列の範囲取得は無理でした。エディターで最初からRange("E1:E5","G1:G5").Selectと書いて処理を行う列を指定しておけば1行目~5行目にだけ処理を施すというのはできましたが、「任意選択した列の1行目~5行目に処理を施す」となると、アドレスの取得方法が無かったので無理でした。探してみたけど駄目でした。 私自身試行錯誤を繰り返しました。試してないと言われるのは心外です。 釣りでもなんでもないんです。本当に詰まってしまったから質問したんです。自分の知識だけでは解決が難しいと判断したから質問したんです。回答者様はただひたすら「調べろ。検証しろ。」とおっしゃっていますが、それはなんのためにおっしゃっているのでしょうか。調べて検証して、結局分からなくて質問をした自分にそれを言われても困ります。なんのために回答をくれているのかわかりません。ごめんなさい。
- 0909union
- ベストアンサー率39% (325/818)
偶然にもNO2の方と意見がいっちしてようで、びっくりしています。 言っておきますが、No2とNo1は関係ないので、そこんとこよろしく。 >それをRange("E1:E12,G1:G12,I1:I12").Selectに変換するなんて、たぶんできないですよね それでいいんです。このような発想を、”机上の空論”というのです。実際にやってみましたか? このようにできるのか、できないのかを実際にやってみて、試行錯誤するのが初心者です。 みんなやっています。そこで、いろんなやり方があるのだと理解が深まるのです。 開発は、まず理論武装します。その次に、それを実践するために、設計します。その設計段階で、理論と合わないところや、やり方ににつまります。それで、実際に、実験をしてみます。 その実験は、検証といって、ただやるのではなく、あらゆる場合も想定して、ケースを作るのです。例えば3つの物の組み合わせは、3X3=9通りが理論ですね。 実証するときは、例えば、トランプを用意して、実際に、組み合わせを並べます。これが実証です。 この事例は簡単な話なのでイメージできないと思いますが、このようにすると見えないものが見えてくるのが実証実験です。何も見えないのなら、才能が無いということで、あきらめてください。 あなたの場合、やりもしないで、ただ子供が口をあけてまっているみたいに、「できないですよね」。 別に質問者ができようと、できまいと、回答者には何の関係もありません。あ、そ。で終わりです。 金をもらっているわけでもないし、責任があるわけでもない。個人的に講習料をいただけるなら別ですが・・・ ちなみに、ちゃんとコードを分析していないですよね??? >たぶんできないですよね。 それはちゃんとマニュアルみましたか? エクセルに付属しているヘルプにリファレンスがあるので、そこを見れば、何が引数になるか、書式がでています。見ていないことがばればれですよね。 さらにいえば、このコードのポイントは、セレクトして、アクティブです。それでアクティブになったセレクションイオブジェクトになるわけです。 GUIソフトはGUI的にといったはずです。 ためさないということは、ただの釣りの質問ですよね。
- imogasi
- ベストアンサー率27% (4737/17069)
初心者にとって、大事なことを忘れていませんか。 それはマクロの記録を採って、それでは記録が採れない問題化、使えないか検討し、修正箇所・方法を勉強することです。 ーー 本件はマクロの記録を採ってみると C列とF列の例で Sub test01() Range("C1:C12,F1:F12").Select With Selection .MergeCells = False End With End Sub となりました。(一部行を不要として削除してます。) まずこれ(または一部修正して)を実行して、質問者が検討をして、それではニーズに合わない場合、それを柱にして質問をするぐらいしてほしい。 ーー 範囲全域の結合セルをすべて解除するなら、全セルについて繰り回しをする必要ないのは知っているのかな。 書式はセル範囲の全体に一発で設定できるのだ。
お礼
回答ありがとうございます。初心者なのでWith~End Withがあるのを知りませんでした。それからお言葉ですが、散々一人で悩んで試行錯誤して、どうしても駄目だったので質問をしました。検討しまくってこの結果でした。最初からそれをしてないと思われるのは少し残念です。 それから質問にあるように、私は選択したセル全体にではなく、全選択した列の一部のセルにだけ処理を施したいんです(たとえばC列を全選択したら、C1~C12のセルにだけ結合解除を行う等)。回答者様の回答でたとえるなら、Range("C1:C12,F1:F12").Selectの「"C1:C12,F1:F12"」の部分をどう取得したら良いのか分からないです。検索してもどこにも載ってないですし。
- 0909union
- ベストアンサー率39% (325/818)
Range("E:E,G:G,I:I").Select Range("I1").Activate With Selection .VerticalAlignment = xlCenter .WrapText = False .Orientation = 0 .AddIndent = False .ShrinkToFit = False .ReadingOrder = xlContext .MergeCells = False End With を改良してつかってください。マクロの記録を使ってだしたものです。 私はこうして自動かしています。もっと早く解決する方法ですね。できなかったときに、何のオブジェクトなんだと考えると、理解が深まります。アクティブな物に対して行うものと、プログラム的に、セル選択、処理だと、あれれれ、というのが多いのがエクセル、ワード、オブジェクトです。 GUIソフトは、GUI的に処理するのが無難です。
お礼
回答ありがとうございます。初心者であるため、With~End Withというものがあるのを知りませんでした。ただ、これだとE列・G列・I列のすべてのセルに処理を施してしまいます。私はE列・G列・I列の「一部の」セルにだけ処理を施したいので、回答者様の回答でたとえるなら1行目はRange("E1:E12,G1:G12,I1:I12").Selectとなるように書かなければいけないですよね。 任意の列を全選択した後でそれが可能なのでしょうか?列を全選択したらRange("E:E,G:G,I:I").Selectになりますけど、それをRange("E1:E12,G1:G12,I1:I12").Selectに変換するなんて、たぶんできないですよね。
お礼
ご回答ありがとうございます。Areaを使うと複数の連続してない範囲についての処理ができるんですね。これを改造した結果、無事に目的のマクロを作成することができました。とても助かりました。ありがとうございました。