🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
VBA

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

Q&A

解決済

5回答

4378閲覧

エクセル 範囲内で重複しているデータを一意にしたい。セルは詰めないで空欄にしたい。

kumiko

総合スコア48

VBA

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

0グッド

0クリップ

投稿2019/10/21 04:54

前提・実現したいこと

範囲内で重複しているデータを一意にしたい。セルは詰めないで空欄にしたい。

おしえてgoo で以下のような質問があったのですが↓

VBAで重複するデータがあれば1個だけ残して他の重複セルを""(空白)にしたいのですが
範囲D5:D36に重複するデータがあれば、
1個だけ残して、他の重複セルに""(空白)を書き込みたいのですが
VBAではどう書けばよいでしょうか

D5:D36に下記のような空白を含むデータがあった時に
山田と書かれたセルは2つあるので、ひとつ残して、もうひとつは空白にしたいです
同じように高橋は3つあるので、ひとつ残して、あとの2つは空白にしたいです

山田
高橋
佐藤
空白
空白
鈴木
山田
空白
高橋
高橋

ベストアンサーはこれでした↓

詰めないで良いのですね?
この位ならば Dictionary 機能を使わなくてもどうにかなりそうだけど、行が増えた時に圧倒的に早くなりますので覚えておくと便利です。


Sub Sample()
Dim 辞書 As Object
Dim 行 As Long
Application.ScreenUpdating = False
Set 辞書 = CreateObject("Scripting.Dictionary")
For 行 = 5 To 36
If 辞書.Exists(Cells(行, 4).Text) Then
Cells(行, 4).ClearContents
Else
辞書.Add Cells(行, 4).Text, 行
End If
Next
Set 辞書 = Nothing
Application.ScreenUpdating = True
End Sub


###私の質問なんですが、 一列だけではなく範囲内の重複を検索して一意だけ残して他を空欄にしたい。
おそらくやりたいことは一致しているのですが質問は一列だけを検索しており、一列以上、たとえばA3セル~C8セルの範囲内で同じことをしたい場合はどのようにかきかえたらよいのでしょうか。
一意が残れば空白に変換する重複データはどこのでもかまいません。

空白 空白 空白
空白 空白 空白
山田 高橋 高橋
山田 佐藤 佐藤
鈴木 高橋 高橋
山田 鈴木 山田
高橋 佐藤 高橋
高橋 鈴木 高橋

ちなみにexcelの機能の重複の削除ですとセルを詰めてしまうのでやりたいことに使えないのです…。

補足情報(FW/ツールのバージョンなど)

excel2010

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

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

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

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

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

guest

回答5

0

おそらくやりたいことは一致しているのですが質問は一列だけを検索しており、一列以上、たとえばA3セル~C8セルの範囲内で同じことをしたい場合はどのようにかきかえたらよいのでしょうか。
一意が残れば空白に変換する重複データはどこのでもかまいません。

現状のコードをなるべく活かすなら、下記のような感じでしょうか。(Dictionaryを活用)

vba

1Sub Sample2() 2 Application.ScreenUpdating = False 3 4 Dim 辞書 As Object 5 Set 辞書 = CreateObject("Scripting.Dictionary") 6 7 Dim セル範囲 As Range 8 Set セル範囲 = Range("A3:C8") 9 10 Dim セル As Range 11 For Each セル In セル範囲 12 If 辞書.Exists(セル.Text) Then 13 セル.ClearContents 14 Else 15 辞書.Add セル.Text, 辞書.Count 16 End If 17 Next 18 Set 辞書 = Nothing 19 Application.ScreenUpdating = True 20End Sub

ttyp03さんと被っちゃた(;^ω^)

投稿2019/10/21 06:54

編集2019/10/21 06:57
hatena19

総合スコア34073

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

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

0

ベストアンサー

ご提示いただいたコードを碌に見もせず回答してしまったので改めて回答します。
こちらはご提示のコードをベースに最小限の修正を行ったものです。
おそらくこれが求めているものと思われます。
ご確認ください。

VBA

1Sub Sample() 2 Dim 辞書 As Object 3 Dim c As Range 4 Application.ScreenUpdating = False 5 Set 辞書 = CreateObject("Scripting.Dictionary") 6 For Each c In Range("A1:C8") 7 If 辞書.Exists(c.Text) Then 8 c.ClearContents 9 Else 10 辞書.Add c.Text, c.Text 11 End If 12 Next 13 Set 辞書 = Nothing 14 Application.ScreenUpdating = True 15End Sub

.

投稿2019/10/21 06:36

編集2019/10/21 06:37
ttyp03

総合スコア17000

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

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

kumiko

2019/10/23 01:22

すごく困っていたので助けていただいた全部の回答にベストといいたいところですが… 初めに回答いただき、質問に対しての回答も記載いただいたのでttyp03さんに。 ありがとうございます。vbaはずいぶん前にかじってふわーっとしか覚えていない状態でした。 皆様の回答をじっくり見直したいと思います。
guest

0

難しく考えなくても、
手動でやるなら、どうやるかなぁ。。。っていう手順を考えたらいいと思います。

手動でやるなら、
左上から順番にセルを見て行く
1番目のセルの値を覚えておいて、同じ値があるかセル範囲を見て行く
同じ値があったら、空白に置換。
全部消えちゃったら、覚えている値をもう一回同じセルに書く
これを重複が無くなるまで繰り返せばいいのでは?

ExcelVBA

1Sub test() 2 Dim Rng As Range 3 Dim c As Range 4 Dim s As String 5 6 Set Rng = Range("A3:C8") 7 Do 8 For Each c In Rng.SpecialCells(xlCellTypeConstants).Cells 9 i = WorksheetFunction.CountIf(Rng, c.Value) 10 If i > 1 Then 11 s = c.Value 12 Rng.Replace s, "" 13 c.Value = s 14 Exit For 15 End If 16 Next 17 Loop Until i = 0 18End Sub

ま、いくつか書き方や、別の考え方もあるとは思いますが、
基本は繰り返していくことになりますので、
Do~LoopやFor~Nextなどの構文を覚えましょう。

う~ん。ぱっと、瞬発的に書いちゃいましたが、
敢えて、CountIfで、数えてみないでも、
置換機能を無条件に繰り返した方が処理が速いかも?

ExcelVBA

1Sub test2() 2 Dim Rng As Range 3 Dim c As Range 4 Dim s As String 5 6 Set Rng = Range("A3:C8") 7 8 For Each c In Rng 9 If IsEmpty(c.Value) = False Then 10 s = c.Value 11 Rng.Replace s, "" 12 c.Value = s 13 End If 14 Next 15End Sub

サンプルは最良のやり方ではないと思いますが、
高速化のコツはループの回数及びセルの読み書きの回数を減らすことです。
まずは希望の結果が出る方法を言葉にするところから始めてみてください。

投稿2019/10/21 06:29

mattuwan

総合スコア2163

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

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

0

検索の順序にもよりますね。
添付図の方式1(A列、B列、C列の順に検索)の場合
高橋はA7が残ります。
方式2(3行、4行、5行の順に検索)の場合、
高橋はB3が残ります。
添付図

どちらを希望されますか。

投稿2019/10/21 06:15

tatsu99

総合スコア5493

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

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

0

ベタな作りですが書いてみました。
コメントも書いておいたので解析してみてください。
ネストが深いのがちょっと自分的にはちょっとアレなんですが、基本的な流れはこうなるしかないかと思います。
対象範囲が巨大な場合パフォーマンスはよくないと思いますがまずはこれを回答とします。

VBA

1Dim r As Range 2Dim c As Range 3Dim f As Range 4Dim fn As Range 5 6' 対象の範囲 7Set r = Range("A1:C8") 8 9' 対象の範囲の各セルでループ 10For Each c In r 11 ' セルが空白ではないとき 12 If c <> "" Then 13 ' 対象の範囲内の同じ値を検索 14 Set f = r.Find(c, LookAt:=xlWhole) 15 ' 見つかった 16 If Not f Is Nothing Then 17 ' 見つかった最初のセルを保持 18 Set fn = f 19 Do 20 ' 次のセルを検索 21 Set fn = r.FindNext(fn) 22 ' 最初のセル位置に戻ったら抜ける 23 If f.Row = fn.Row And f.Column = fn.Column Then Exit Do 24 ' 見つかったセルの値を空白に置き換える 25 fn = "" 26 ' 無限ループ対策 27 DoEvents 28 Loop 29 End If 30 End If 31Next 32

投稿2019/10/21 06:01

ttyp03

総合スコア17000

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問