
【実録】見た目は1枚、中身は大量……エクセルに潜む「重なり図形」の地獄
「VBA? マクロ? 何それ、おいしいの?^^」
はい、こんにちは。トム子です。
普段はこのブログで海外ドラマや映画のキャラを愛でたりいじったりしている私ですが、今日はちょっと……いや、かなり珍しくエクセルVBAの話をしようと思います。
「え、トム子さん、急に意識高い系エンジニアに転生したの?」 と思った方、安心してください。そんなわけありませんww
私は今でも、コードの森に迷い込むと『ウォーキング・デッド』のシーズン1の最初のリックくらい絶望的な顔になりますし、専門用語が並ぶ参考書は3ページ目で窓から投げ捨てるタイプの人間です^^
きっかけは、仕事での作業がどうしてもやりたくなかった。。。
セルに重なった画像を消して1枚にする作業があったのですが、もうミスの連発ww
上司にWチェックしてもらう時に、
「トム子さん、また消し忘れですよ。気を付けてくださいね」って毎度言われました。
でも、この「重なり」、目で見ても絶対に分かりません。
何十箇所のセルに載った画像を一枚ずつ手でどけて確認するなんて、地獄ですよ。。。Orz _| ̄|
不器用を殺す仕事をなくすために、専門知識ゼロ・執念100%で生み出したのが『我流の適当マクロ』です。
今日は、難しい理屈はすべて放り投げて、「とりあえずコピペで動けばOK!」という精神で、図形や画像を操る魔法の呪文を共有します。
「VBA、難しそうで手が出ない…」 「ググっても専門用語すぎて意味不明w」
そんな風に思っている初心者のあなた、ちょっとおいで。
私語多めでお送りしますが、読み終わる頃には「あれ、マクロって意外と私の味方かも?」と思えるはずですよ^^
これだけ知っていれば大丈夫!図形(画像も!)を操る3つの鉄則
エクセルの図形って、実はセルの中に住んでいるわけじゃなくて、
シートの上にプカプカ浮いている状態なんです。
だから、セルを消しても図形は消えない……。
この浮遊感が厄介の種なのよねー
「図形を処理するマクロは理解するのが面倒くさそうだな」って思ったあなた!
仕組みを簡略化したルールがあるので紹介します。
以下の3つのルールを、呪文のように唱えてみて!(^▽^)/

これだけ知っていれば大丈夫!図形(画像も!)を操る3つの鉄則
「このセルの中にいるアイツだけを狙い撃ち!」っていう操作は、
実は直接はできなんです。。。
シートという大海原に浮かんでいる図形を、まずは一網打尽に捕まえる必要があります。
下記のコードをご覧あれ。
'【B2セルに左上の角が載ってるヤツ(図形)を探す呪文】
For Each shp In ActiveSheet.Shapes
'もし、図形(shp)の左上が「2行目」かつ「2列目(B列)」だったら…
If shp.TopLeftCell.Row = 2 And shp.TopLeftCell.Column = 2 Then
'~ここに、その図形にしたい処理(削除とか)を書く~
End If
Next shp
For Each shp In ActiveSheet.Shapesでシート内の図形を下記の1枚ずつ順番に巡って、お前の居場所はどこだ?とif文で問い詰めるのがスタンダードなやり方です。
図形が「今どこに座っているか」を確認するには、shp.TopLeftCell.Row(行番号)や Column(列番号)を使います。
これで「お前、B2にいるな!」って突き止めるわけ。
ただし、特定できるのは図形の角が載っているセルです。
【コピペするだけ!】実務で使える呪文を紹介
何も理解したくない!理解なんてめんどくさいわー!って人のために、
ファイルの読み込み~処理をコピペだけでできるコードを用意しました。
できるだけ、読者の皆さんが編集せずに使えるように書いてあります。
実用的なものを2つ紹介します☆
- 図形が2枚以上重なっているセルを水色にする
- 最前面以外の図形を削除する
図形が2枚以上重なっているセルを水色にする
このコードは、セルに図形の角が2つ以上重なっていれば、セルが水色になる呪文です。
ファイルの読み込みまで、完全コピペでいけちゃいます^ ^
ただし、シートの指定はSheets(1)としましたので、適宜変えてください。
Sub 図形が2枚以上重なっているセルに色を付ける()
Dim ReadBook_Path As String
Dim RB As Workbook
Dim i As Long
Dim r As Long , c As Long '処理中の図形の行/列番号
'↓添え字:処理中の図形の配置(行番号,列番号)
Dim ShapeCells(10000, 10000) As Variant 'セルに重なった図形の数(図形の角)
'ファイルの読み込み
ReadBook_Path = Application.GetOpenFilename("ブック, *.xls?")
If ReadBook_Path <> "False" Then
Set RB = Workbooks.Open(ReadBook_Path)
Else
MsgBox "キャンセルされました"
Exit Sub
End If
With RB.Sheets(1)
'シート内の全ての図形をひとつずつ巡る
For Each shp In .Shapes
r = shp.TopLeftCell.Row
c = shp.TopLeftCell.Column
ShapeCells(r, c) = ShapeCells(r, c) + 1
If ShapeCells(r, c) >= 2 Then
.Cells(r, c).Interior.ColorIndex = 37 ' セルを水色にする
End If
Next
End With
MsgBox "完了"
End Sub
For Each shp In .Shapesでシート内の図形を一つづつアクセスします。
図形がアクセスされる度に、ShapeCells(図形の行番号, 列番号)の値が1足されます。
If文でShapeCellsが2以上だったら、セルが水色になります。
色のオプションも適宜変えてください(^^♪
補足:ShapeCells()は図形の行番号と列番号を添え字とする配列です。配列の添え字ですが、最大1000個まで登録できるように下記のコードでは設定しています。これは、必要に応じて増やしてください。ただし、値が大きすぎると、エラー(メモリが不足しています)がでるので注意です。
わざわざ配列を使わずとも、一発でセルの上に載っている図形の数を特定できる方法でやれば?と思った方もいるかもしれません。
しかし、それがないんです。。。
なぜなら、上述もしましたが、図形はセルに属さず、ただシートに浮いているだけだから。。。
シート内の図形はSheet.Shapes.Countで数がわかります。
でも、Range().Shapes.Countは使えないんです。
なんて使い勝手が悪いんだ(#`Д´)凸
セル単位で使いたいことぐらいわかるだろーーー!って毎度思います。
最前面以外の図形を削除する
Sub 最前面以外の図形を削除する()
Dim ReadBook_Path As String
Dim RB As Workbook
Dim i As Long
Dim r As Long , c As Long '処理中の図形の行/列番号
'↓添え字:処理中の図形の配置(行番号,列番号)
Dim ShapeCells(10000, 10000) As Variant 'セルに重なった図形の数(図形の角)
Dim A As Range
'ファイルの読み込み
ReadBook_Path = Application.GetOpenFilename("ブック, *.xls?")
If ReadBook_Path <> "False" Then
Set RB = Workbooks.Open(ReadBook_Path)
Else
MsgBox "キャンセルされました"
Exit Sub
End If
With RB.Sheets(1)
For i = .Shapes.Count To 1 Step-1
Set A = .Shapes(i).TopLeftCell
ShapeCells(A.Row, A.Column) = ShapeCells(A.Row, A.Column)+1
If ShapeCells(A.Row, A.Column)>= 2 Then
.Shapes(i).Delete
End If
Next i
End With
MsgBox "完了"
End Sub
突然ですが、
シート内にある5番目の図形は、VBAではSheets.Shapes(5)です。
これはシート内にある図形に番号(インデックス)が割り振られるからです。
この図形のインデックスはどう決まるかというと、、
①図形の左角があるセルを、図形の所属セルとみなし、
②同じセル内の図形で、一番下から昇順に番号が振られていき、
③そのセルが終わったら、隣のセルも同じように振られていきます。

図形には番号(インデックス)が振られる!For Each文は「一番下の図形」からスタートします。
For i = .Shapes.Count To 1 Step-1 で 、
図形のインデックスiが降順にまわることで、
Shapes(i)で表面にある図形からアクセスされます。
If ShapeCells(A.Row, A.Column)>= 2 Then の条件を満たすと、
処理中のiは一番上の図形に対して、
背面にいる図形のインデックスということになります。
これで、削除するべきShapes(i)かが判断できるのだー
私の執念、見たかーー!!(ドヤァ!)
まとめ
- 図形が2枚以上重なっているセルを水色にする
- 最前面以外の図形を削除する
上記VBAの紹介でした。
ここまで読んでいただきありがとうございました!
胆としては、図形はシートに浮いているだけ、セルには住んでいないということですね。図形の角が、セルのどの位置にあるかは取得できることを利用してコーディングしていきましょう。
皆様のお役に立てれば幸いです。
では、また!
”【悲報】私のエクセル、画像の下に画像がある……。図形の重なりをあぶり出し、最前面以外を消し去る執念のコード”でした☆


コメント