VBAで複数列に対する処理方法

このQ&Aのポイント
  • VBAを使用して離れた複数の列に対して処理を行う方法を教えてください。
  • 具体的には、任意の列を全選択し、その中の一部の行に対してセル結合解除を行いたいです。
  • 現在、1列だけの場合は処理ができるのですが、複数列に対して処理を行う方法がわかりません。
回答を見る
  • ベストアンサー

VBAで、離れた複数の列に対して処理を施すには?

VBAでマクロを組んでいたところ、問題が出てきたので質問させてください。 1.任意の列を全選択する(たとえばA列とC列という離れた列です) 2.その列の中でも、すべての行にではなく、数行にだけセル結合解除という処理を施す というマクロを組もうとしています。 しかし、全選択した列の一部の行(画像参照)にだけ処理を施す、というのができません。 1列だけ全選択→セル結合解除、というのはできるのですが、複数の列(しかも列同士が隣り合っていない)に対して処理を施すというのがうまくいかず…。 以下のようにマクロを作成してみたのですが、どこが問題になってるのでしょうか? アドバイスいただけると幸いです。 Sub test1()  Dim intX_1 As Long  Dim intX_2 As Long  Dim rg1 As Range  Dim rg2 As Range  Set rg1 = Range(CStr(ActiveWindow.RangeSelection.Address))  For Each rg2 In rg1 '選択した列のうち、2行目~最後のデータが存在する行まで処理を行う intIX_1 = 2 While rg2(intIX_1) <> "" rg2(intIX_1).MergeCells = False     intIX_1 = intIX_1 + 1 If rg2(intIX_1) = "" Then Exit For End If Wend Next End Sub

質問者が選んだベストアンサー

  • ベストアンサー
回答No.5

個別の範囲なら処理できる、しかし複数の選択範囲を個別の範囲にバラす方法が分からない、というのが質問の核のようなので…。 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

kirsch_29
質問者

お礼

ご回答ありがとうございます。Areaを使うと複数の連続してない範囲についての処理ができるんですね。これを改造した結果、無事に目的のマクロを作成することができました。とても助かりました。ありがとうございました。

その他の回答 (5)

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.6

ちょっと横からおじゃまさせていただきます。 オブジェクト変数を使わずに、たとえば 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)で移る方法もあります) ご参考まで。

kirsch_29
質問者

お礼

ご回答ありがとうございます。For Eachを使ってもやり様があるのですね。勉強になりました。 あと質問文にあるintIX_1 = intIX_1 + 1 は行変更のために使ってたものなのは間違いないですし、これだと選択した他の列に移動できないのも分かってました(なので離れた列にも処理を行うには?と質問を投げました)。それは大丈夫です。ただ「intIX_1 = intIX_1 + 当該結合セルの行数(Range(...).MergeArea.Rows.Count)」の部分はとても勉強になりました。ありがとうございました。

  • 0909union
  • ベストアンサー率39% (325/818)
回答No.4

大事な事忘れていました。 よく素人の方だと、バージョンをまったく無視して作る方が多いです。それで、何でできないのかと、よくここで質問されます。 何のバージョンのエクセルを対象にしているか、記載しましょう。もっともちゃんと理解しているなら、最初からバージョンの記載はあるはずですが また、COMからのアクセスは、そのプラットフォームに依存するので、例えばコレクションや引数の指定などは、できない場合もあります。それはマイクロソフトのMSDNのサイトにテクニカル情報として、どうすればいいいか記載があります。 と言うことは、COMで使用している場合は、呼び出し元も記載しないと、明確にできるとかできないとか言い切れるものではありません。

kirsch_29
質問者

お礼

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)
回答No.3

偶然にもNO2の方と意見がいっちしてようで、びっくりしています。 言っておきますが、No2とNo1は関係ないので、そこんとこよろしく。 >それをRange("E1:E12,G1:G12,I1:I12").Selectに変換するなんて、たぶんできないですよね それでいいんです。このような発想を、”机上の空論”というのです。実際にやってみましたか? このようにできるのか、できないのかを実際にやってみて、試行錯誤するのが初心者です。 みんなやっています。そこで、いろんなやり方があるのだと理解が深まるのです。 開発は、まず理論武装します。その次に、それを実践するために、設計します。その設計段階で、理論と合わないところや、やり方ににつまります。それで、実際に、実験をしてみます。 その実験は、検証といって、ただやるのではなく、あらゆる場合も想定して、ケースを作るのです。例えば3つの物の組み合わせは、3X3=9通りが理論ですね。 実証するときは、例えば、トランプを用意して、実際に、組み合わせを並べます。これが実証です。 この事例は簡単な話なのでイメージできないと思いますが、このようにすると見えないものが見えてくるのが実証実験です。何も見えないのなら、才能が無いということで、あきらめてください。 あなたの場合、やりもしないで、ただ子供が口をあけてまっているみたいに、「できないですよね」。 別に質問者ができようと、できまいと、回答者には何の関係もありません。あ、そ。で終わりです。 金をもらっているわけでもないし、責任があるわけでもない。個人的に講習料をいただけるなら別ですが・・・ ちなみに、ちゃんとコードを分析していないですよね??? >たぶんできないですよね。 それはちゃんとマニュアルみましたか? エクセルに付属しているヘルプにリファレンスがあるので、そこを見れば、何が引数になるか、書式がでています。見ていないことがばればれですよね。 さらにいえば、このコードのポイントは、セレクトして、アクティブです。それでアクティブになったセレクションイオブジェクトになるわけです。 GUIソフトはGUI的にといったはずです。 ためさないということは、ただの釣りの質問ですよね。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.2

初心者にとって、大事なことを忘れていませんか。 それはマクロの記録を採って、それでは記録が採れない問題化、使えないか検討し、修正箇所・方法を勉強することです。 ーー 本件はマクロの記録を採ってみると C列とF列の例で Sub test01() Range("C1:C12,F1:F12").Select With Selection .MergeCells = False End With End Sub となりました。(一部行を不要として削除してます。) まずこれ(または一部修正して)を実行して、質問者が検討をして、それではニーズに合わない場合、それを柱にして質問をするぐらいしてほしい。 ーー 範囲全域の結合セルをすべて解除するなら、全セルについて繰り回しをする必要ないのは知っているのかな。 書式はセル範囲の全体に一発で設定できるのだ。

kirsch_29
質問者

お礼

回答ありがとうございます。初心者なのでWith~End Withがあるのを知りませんでした。それからお言葉ですが、散々一人で悩んで試行錯誤して、どうしても駄目だったので質問をしました。検討しまくってこの結果でした。最初からそれをしてないと思われるのは少し残念です。 それから質問にあるように、私は選択したセル全体にではなく、全選択した列の一部のセルにだけ処理を施したいんです(たとえばC列を全選択したら、C1~C12のセルにだけ結合解除を行う等)。回答者様の回答でたとえるなら、Range("C1:C12,F1:F12").Selectの「"C1:C12,F1:F12"」の部分をどう取得したら良いのか分からないです。検索してもどこにも載ってないですし。

  • 0909union
  • ベストアンサー率39% (325/818)
回答No.1

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的に処理するのが無難です。

kirsch_29
質問者

お礼

回答ありがとうございます。初心者であるため、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に変換するなんて、たぶんできないですよね。

関連するQ&A

  • VBA エクセル 列の並び替え

    左から右にA、B、Cと値が入っています。 ABC以外の文字が列に入っていたら、削除するというマクロを組みましたが、範囲を設定するところでエラーが出てしまいました。 なぜでしょうか? 教えて下さい。 Sub arrange() Dim rg As Range Dim i As Long i = 1 Do rg = Cells(i, 1) If rg <> "A" And rg <> "B" And rg <> "C" Then Range(i & ":" & i).Delete End If i = i + 1 Loop Until (i & "1") = "" End Sub

  • VBA最終列の取得/不規則な処理

    VBAにて、最終列の取得ができません。 また、繰り返し処理を3列処理、step5、3列処理、step5…と繰り返し行う方法もご教授いただきたいです。 エクセルはo365を使用しております。 ①最終列の取得 実際は300列近くの表になります。 最終行は取得できたのですが、最終列がなぜかエラーも出ず、処理が行われません。 ②不規則な繰り返し処理 画像の水色部分のみ処理を行いたいです。 3列処理と記載したのですが、セル結合しているので、考え方が合っているのかも不明です。 塗りつぶされているセル一つ一つに処理を行いたいです。 また、行列共に可変します。 実行したいマクロは、選択したブックのSheets(1)の表の中の水色に入力されている文字列が「1」か「2」か判断するというものです。 「1」と入力されていれば → 別ブックのA1セルに1をカウント 「2」と入力されていれば → 別ブックのB1セルに1をカウント ※水色セルは参考で用意したものなので、実際は塗りつぶしされていません。 ※空白のセルもあります ①②の解消法のご教授をよろしくお願い致します。 =============================================== Option Explicit Sub kurikaeshi() Dim retu As Long, gyou As Long Dim File As Workbook Set File = Workbooks("test.xlsx") Dim ws1 As Worksheet, ws2 As Worksheet Set ws1 = File.Sheets(1) Set ws2 = ThisWorkbook.Sheets(1) Workbooks.Open FileName:=ThisWorkbook.Path & "/" & File For retu = 2 To ws1.Cells(4, ws1.Columns.Count).End(xlToLeft).Column 'ここが処理されません For gyou = 4 To ws1.Cells(ws1.Rows.Count, 2).End(xlUp).Rows If ws1.Cells(gyou, retu).Value = "1" Then ws2.Range("A1") = ws2.Range("A1") + 1 If ws1.Cells(gyou, retu).Value = "2" Then ws2.Range("B1") = ws2.Range("B1") + 1 End If Else Exit Sub End If Next gyou Next retu End Sub

  • vbaの繰り返し処理について

    vbaです。 Sub Test1() Dim Str As String Dim Pnt1 As Long Dim Pnt2 As Long Str = Range("A1") Pnt1 = InStr(Str, "重 http://") If Pnt1 <= 0 Then Exit Sub Pnt2 = InStr(Pnt1, Str, "要") If Pnt2 <= 0 Then Range("B1") = Mid(Str, Pnt1 + 2) Else Range("B1") = Mid(Str, Pnt1 + 2, Pnt2 - (Pnt1 + 2)) End If End Sub という式でA1からA2.A3と下にURLが入っており空欄になるまで同じ処理をしたいのですがどのように変更すれば作動しますでしょうか?

  • VBA マクロ処理時間の短縮について

    下記のコードを作りましたが、マクロを実行すると砂時計マークが表示されて、処理が終了するまでに30秒くらいかかります。 コードを変更して、マクロ処理時間を短縮する事はできないでしょうか? Sub A列のコピー() Dim rw2 As Long Dim rw1 As Long Dim newdate As Date With Worksheets("sheet1") rw2 = .cells(.Rows.Count, "c").End(xlUp).Row newdate = .Range("c" & rw2).value For rw1 = rw2 - 1 To 1 Step -1 If .Range("c" & rw1).value <> newdate Then Exit For Next rw1 .Range(.cells(rw1 + 1, 1), .cells(rw2, 1)).Copy Worksheets("sheet2").Range("v6").PasteSpecial xlValue If rw1 + 26 <= rw2 Then .Range(.cells(rw1 + 26, 1), .cells(rw2, 1)).Copy Worksheets("sheet2").Range("v40").PasteSpecial xlValue Application.CutCopyMode = False End If Application.CutCopyMode = False End With End Sub 各セルは、6000行くらいまで表示されています。  よろしくお願いします。

  • VBA 請求書の自動印刷について

    VBAで請求書の連続印刷について質問です。 Sheet("基本情報")のA列に請求書No. B列に請求日が記載されております。 ComboBoxで入力されている請求日を選択することで、該当の全データを請求書フォーマットに転記して、全て印刷するマクロを組んでみたのですがうまくいきません。 流れとしては以下の通りです。 1、ComboBoxで請求日を選択(20日) 2、Sheet("基本情報")から、請求日が20日に該当するデータをSheet("請求書")に転記 3、Sheet("基本情報")の請求日が20日でA列の請求書Noと一致する、Sheet("詳細")の該当データを Sheet("請求書")に転記 4、印刷したら、入力データをクリアしてから、次の該当データを転記 Loop と、したいのですが、1~入力データのクリアまでは問題なく作動するのですが、次の該当データに移行しません。 MsgBoxでAddressの表示を行ったところ、たまに関係ないセルのアドレスの表示も確認でき、全くわからなくなってしまいました。 何卒、御教授の程お願い致します。 また、作成中のため、記述の整理は出来ておりませんが、併せて御教示頂ければ幸いです。 Private Sub CommandButton1_Click() Dim Ws As Worksheet, ws2 As Worksheet, pSht As Worksheet Dim StrFind As String, Res As String, _ firstAddress As String, buf As String Dim rg As Range, rg1 As Range Dim 選択行 As Integer, 選択行1 As Integer Dim i As Long, A As Long, MinRow As Long buf = Year(Date) & "/" & Month(Date) & "/" StrFind = ComboBox1.Value Set Ws = Worksheets("請求書") Set ws2 = Worksheets("詳細") Set pSht = Worksheets("基本情報") If StrFind = "" Then MsgBox "送付日を指定してください。" Exit Sub End If With pSht Set rg = .Columns(2).Find(What:=StrFind, LookAt:=xlWhole) 選択行 = rg.Row Set rg1 = ws2.Columns(1).Find(What:=.Cells(選択行, 1)) 選択行1 = rg1.Row If Not rg Is Nothing Then firstAddress = rg.Address Do DoEvents '~~~~~ここに転記の構文 およそ200行前後~~~~~ Set rg = .Columns(2).FindNext(rg) If rg Is Nothing Then Exit Do Loop Until rg.Address = firstAddress Unload Me End If End With End Sub

  • 複数の列を繋げてA列に入れたい VBA

    aaa aaa  bbb aaa  bbb  ccc aaa (A列にaaa、B列にbbb、C列にcccが入ってます) と言うデータがあるのですが 全てA列に入れて aaa aaabbb aaabbbccc aaa としたいです。 ・最終列は必ずしもCではないのです。(Dの場合もEの場合もある) ・最終行も変化します。 Sub 分かれてる列を繋げる() Dim Col As Long Dim Row As Long For Row = 1 To Range("a65536").End(xlUp).Row   For Col = 1 To Cells(Row, 256).End(xlToLeft).Column    Cells(Row, 1) = Cells(Row, 1) & Cells(Row, 2) & Cells(Row, 3)    Next Col Next Row End Sub をやってみましたが、 aaa aaabbbbbb aaabbbcccbbbcccbbbccc aaa となってしまい、 欲しい結果とは違くなってしまいます。

  • エクセルVBAについて

    エクセルVBAについて 下にある、1行目に入力された数値の、選択したセルの数値を、B5セルに表示させるマクロなのですが、1行目が結合していると、うまくB5セルに表示できません。 Private Sub Worksheet_SelectionChange(ByVal Target As Range)  If Target.Count > 1 Then Exit Sub    '●複数セル選択は無視  If Target.Row <> 1 Then Exit Sub    '●1行目以外の選択は無視  If Target.Column > 6 Then Exit Sub   '●F列目以降の選択は無視  If Target.Value = "" Then Exit Sub   '●選択セルが未入力なら無視    Range("B5").Value = Target.Value End Sub このマクロで、結合しているセルをB5に表示させることはできますでしょうか? 1行目で選択するセルは、すべて2つのセルが結合しています。 よろしくお願いいたします。

  • エクセル2003のVBAで列を指定

    エクセルで特定の列の2~10行目に対して、ある作業をする場合、列を指定する方法は以下のどれがいいでしょうか?あるいはもっといい方法があれば教えてください。 実際には列は約40列(固定)、行は1~2万行(変動)程度で、作業はもっと複雑です。 Sub test01() Dim col Dim i As Long, n As Long For Each col In Array(1, 3, 7, 8, 11) '列番号で指定 For i = 2 To 10 n = n + 1 Cells(i, col).Value = n Next i Next col End Sub Sub test02() Dim col Dim i As Long, n As Long For Each col In Array("A", "C", "G", "H", "K") '列の記号で指定 For i = 2 To 10 n = n + 1 Cells(i, col).Value = n Next i Next col End Sub Sub test03() Dim col Dim i As Long, n As Long For Each col In Range("A2,C2,G2,H2,K2") 'セルで指定 For i = 2 To 10 n = n + 1 col.Offset(i - 2).Value = n Next i Next col End Sub

  • セル解除後、各行に値をコピーし結合するマクロ

    A1からC3のセルが結合しており、 そのセル結合を解除すると、A列のみ値がコピーされる。 コピーした後、各行ごとにセルを結合していく…… という処理をしたいと思い、 調べて下記のマクロまでなんとかこぎつけました。 Sub セル結合() Dim date1 As Variant Dim range1 As Range Application.DisplayAlerts = False For Each range1 In Selection.Rows If range1(1).MergeCells = False Then range1(1).Merge Else date1 = Selection.Rows(1).Value With range1 .UnMerge .WrapText = False .ShrinkToFit = False Selection.Value = date1 End With End If Next range1 End Sub ※実行範囲に関しては、  任意選択をした範囲にしたいため、  range(1)にて処理を行いました。 困っているのは、上記のマクロを実行すると、 最初の行のみ結合できないということ。 もうひとつが、 セル結合をしない時に値を左端にコピーすると、 文字が自動縮小されてしまいます。 縮小しないようにするには、 どのような処理を入れたら良いでしょうか? お力添え頂けますと幸いです。 よろしくおねがいします。

  • エクセルマクロFor Eachの処理が長い

    エクセル2013です。 皆さんに教えていただいて以下のマクロが完成しました。 サンプルデータ 30行、7列ではあっという間に処理ができたのですが 本番環境 800行、50列ですと 処理時間が長く 青丸がくるくる回っていて、2分後にくらいで終わります。 もう少し早く処理する方法はありますでしょうか? Findで検索して、一括削除? (それはマクロでできるのでしょうか?) よろしくお願いします。 Sub 出荷済削除() Dim 対象セル As Range Dim 対象色 As Long Dim 対象色2 As Long Dim 最終行 Dim 最終列 最終列 = Cells(8, Columns.Count).End(xlToLeft).Column '8行目の最終列を取得 最終行 = Cells(Rows.Count, 1).End(xlUp).Row 'A列の最終行を取得 Application.ScreenUpdating = False '画面切替停止 対象色 = Range("B8").Interior.Color 'セルB8の色を基準色とする 対象色2 = Range("A8").Interior.Color 'セルB8の色を基準色とする For Each 対象セル In Range(Cells(10, 17), Cells(最終行, 最終列)) If 対象セル.Interior.Color = 対象色 Or 対象セル.Interior.Color = 対象色2 Then 対象セル.ClearContents Next 対象セル Application.ScreenUpdating = True '画面切替停止解除 End Sub

専門家に質問してみよう