質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Q&A

解決済

4回答

3109閲覧

vbaにて、Unionでまとめたセル範囲に一回で罫線を引きたい

Usirow

総合スコア364

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

0グッド

0クリップ

投稿2020/08/22 06:03

実現したいこと

VBAにて、csvから情報を読み込んで、それを表に加工するマクロをつくっています。
その中で画像のように、分類1の変わり目に罫線を引きたいと考えています。
目指す形

その実現のため現在のマクロは

・forループでA列を上から順番に検査
・各列を一つ上の値を比較して、値が異なれば(分類1の変わり目)UnionメソッドてRange変数に格納
・ループ終了後にUnionでまとめたRange全体にborderプロパティで罫線を引く(xlEdgeTop)

という挙動をさせ、罫線の処理を一度にまとめています。
Excelのバージョンは2019です。

VBA

1 srw = 6 'テーブルの始まり 2 urw = 19 '表の終わり 3 'ubo = 罫線を引きたいRange 4 For rw = srw To urw 5 6 '分類の変わり目に横線 7 If Cells(rw, 1) <> Cells(rw - 1, 1) Then 8 If ubo Is Nothing Then 9 Set ubo = Range(Cells(rw, 1), Cells(rw, 3)) 10 Else 11 Set ubo = Union(ubo, Range(Cells(rw, 1), Cells(rw, 3))) 12 End If 13 End If 14 15 Next 16 17 Set ubo = Union(ubo, Range(Cells(urw + 1, 1), Cells(urw + 1, 3))) 18 ubo.Borders(xlEdgeTop).LineStyle = xlContinuous 19

現状

現在の状態
実際にマクロを動かすと、画像のようになってしまいます。
どうやら、分類D以降の変わり目が連続してしまっているために、Unionで別々に指定してもひとまとまりの範囲と捉えられてしまっているようです。

Unionのこのような使い方が一般的でないのか、調べても対処法や代替手段が出てきません。
もちろんいざとなればUnionを使わず、ループで各行に直接罫線を引いていけばいいのは重々承知なのですが、できれば罫線を引く処理は一度にまとめてしまいたいです。

もしもこのような処理を実現するやり方があれば、是非ご教授いただきたいです。
よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

代替案を4つ

ExcelVBA

1'セルアドレスの文字を作る 2Sub test1() 3 Dim i As Long 4 Dim a As String 5 6 For i = 6 To 19 7 If Cells(i, 1).Value <> Cells(i + 1, 1).Value Then 8 a = a & "," & Cells(i, 1).Resize(, 3).Address 9 End If 10 Next 11 a = Mid(a, 2) 12 13 Range(a).Borders(xlEdgeBottom).LineStyle = xlContinuous 14End Sub 15 16'セルアドレスの文字を作る2 17Sub test2() 18 Dim r As Range 19 Dim a As String 20 21 For Each r In Range("A5").CurrentRegion.Rows 22 If r.Cells(1, 1).Value <> r.Cells(2, 1).Value Then 23 a = a & "," & r.Cells(1, 1).Resize(, 3).Address 24 End If 25 Next 26 a = Mid(a, 2) 27 Range(a).Borders(xlEdgeBottom).LineStyle = xlContinuous 28End Sub 29 30'小計機能を使ってキーブレーク箇所に行挿入しセル範囲を分ける 31Sub test3() 32 With Range("A5").CurrentRegion 33 .Subtotal GroupBy:=1, Function:=xlCount, TotalList:=3 34 End With 35 With Range("A5").CurrentRegion 36 Intersect(.Cells, .Columns(3).SpecialCells(xlCellTypeConstants).EntireRow) _ 37 .Borders(xlEdgeBottom).LineStyle = xlContinuous 38 .RemoveSubtotal 39 End With 40End Sub 41 42'セルに目印を入れオートフィルターで抽出 43Sub test4() 44 Dim rngTable As Range 45 Dim rngTemporarily As Range 46 Dim c As Range 47 Dim v As Variant 48 Dim i As Long 49 50 Set rngTable = Range("A5").CurrentRegion 51 Set rngTemporarily = rngTable.Columns(4) 52 v = WorksheetFunction.Transpose(rngTemporarily) 53 54 For i = 1 To rngTable.Rows.Count 55 Set c = rngTable(i, 1) 56 If c.Value <> c.Offset(1).Value Then 57 v(i) = 1 58 End If 59 Next 60 61 rngTemporarily.Value = WorksheetFunction.Transpose(v) 62 63 With Union(rngTable, rngTemporarily) 64 .AutoFilter 4, 1 65 .Resize(, 3).Borders(xlEdgeBottom).LineStyle = xlContinuous 66 .AutoFilter 67 End With 68 rngTemporarily.ClearContents 69End Sub

あ、タイトル行の下に線が入ったり入らなかったりしてます。
サンプルなので微調整願います。
セル範囲の指定の仕方で対象セル範囲を上手く指定してやってください。

投稿2020/08/22 07:04

mattuwan

総合スコア2163

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Usirow

2020/08/22 07:11

いろいろなやり方があるものなのですね。特に3つ目以降は完全に知らないやり方ですので、参考に勉強させていただきます。ありがとうございます!
guest

0

ベストアンサー

Unionだと連続したセル範囲は一つに纏めるという仕様なので、Unionを使うのでは無理ですね。

"A9:C9,A12:C12,A14:C14,A15:C15,A16:C16,A17:C17,A18:C18,A19:C19" というような文字列を生成して、これでRangeを設定して罫線を引けばいいでしょう。

vba

1Sub Sample() 2 Dim srw As Long, urw As Long, rw As Long 3 Dim ubo As String 4 5 srw = 6 'テーブルの始まり 6 urw = 19 '表の終わり 7 For rw = srw To urw 8 '分類の変わり目に横線 9 If Cells(rw, 1) <> Cells(rw - 1, 1) Then 10 ubo = ubo & "," & Cells(rw, 1).Resize(, 3).Address(False, False) 11 End If 12 Next 13 If ubo = "" Then Exit Sub 14 ubo = Mid(ubo, 2) '先頭のカンマ(,)を削除 15 Range(ubo).Borders(xlEdgeBottom).LineStyle = xlContinuous 16End Sub

ただし、Rangeの引数は最大255字までという制限があるので、それを超える時は、その前で罫線を引いて、また、次の行から始めるという処理が必要になります。


255文字制限の対処済みコードです。

vba

1Sub Sample2() 2 Dim targetRng As Range 3 Set targetRng = ActiveSheet.Range("A5").CurrentRegion 4 5 Dim rw As Range, ubo As String 6 For Each rw In targetRng.Columns(1).Cells 7 If rw.Value <> rw.Offset(1).Value Then 8 Dim ad As String 9 ad = "," & rw.Resize(, 3).Address(False, False) 10 If Len(ubo) + Len(ad) <= 255 Then 11 ubo = ubo & ad 12 Else 13 Debug.Print ubo 14 Call DrowBorder(ubo) 15 ubo = ad 16 End If 17 End If 18 Next 19 If ubo = "" Then Exit Sub 20 Call DrowBorder(ubo) 21End Sub 22 23Sub DrowBorder(ubo As String) 24 ubo = Mid(ubo, 2) '先頭のカンマ(,)を削除 25 Range(ubo).Borders(xlEdgeBottom).LineStyle = xlContinuous 26End Sub 27

投稿2020/08/22 06:48

編集2020/08/22 07:21
hatena19

総合スコア34075

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Usirow

2020/08/22 07:01

Range指定を文字列でつくる発想が完全に抜けていました……ありがとうございます!
Usirow

2020/08/23 09:35

わざわざ改良版までつくってくださって本当にありがとうございます。 基本的な考え方は私も同じだったのですが、私の考えたものよりコードがかなりすっきりしていて、よりスマートな仕上がりに見えます。参考にさせていただきます。
guest

0

質問のプログラムでForループが終わった時、変数uboには、union(Range(A6:C6),Range(A10;C10),Range(A13:C13),Range(A15:C19))が入っているはずですから、「現状」のようになると思います。

15行から19行をunionでひとつながりのRange(Range(A15:C19))にした後に、上部(xlEdgeTop)に罫線を引いたのでは、ひとつながりのRangeの上部に罫線が引かれるだけです。

Forループの中で、分類1の変わり目が見つかるたびに、A列からC列にまたがるRangeの上部に罫線を引く教にすれば、希望するような結果が得られると思います。

隣接するRangeのUnionをとったら、隣接するRangeをひとまとめにした大きなRangeが出来ます。
その大きなRangeから、元になったRangeが何であったかという情報を得ることは出来ません。

この質問の源は、unionをとったものが、そのもとになったRangeの情報を保持しているという誤解にあります。

投稿2020/08/22 15:07

coco_bauer

総合スコア6915

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Usirow

2020/08/23 09:31

仰るとおりで、以前この仕組を使った際には隣接するRangeのUnionが発生しないデータだったので、Union内での隣接Rangeの扱いに最初は全く気付いていませんでした。 今回解決とさせていただいた代替案も、考えてみれば当たり前のやり方で、自分の不勉強と思い込みを恥じているところです。 ご指摘ありがとうございます。
guest

0

ほぼhatena19様の回答と同じコードを用いて、文字列でRange範囲を作成することで狙い通りに一度で罫線を引くことが出来ました。

Range指定は255個上限があるとのことですが、今のところそこまで分類が増える予定はないので、これで解決とさせていただきます。もし255個を超えてしまう際は、また考えます。

大変助かりました。ありがとうございました。

投稿2020/08/22 07:06

Usirow

総合スコア364

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hatena19

2020/08/22 07:10

255個ではなく,255文字制限ですので、意外と少ないと思いますので、ご注意ください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問