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

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

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

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

Q&A

解決済

4回答

1273閲覧

VBA 配列格納 重複を拒否

King_of_Flies

総合スコア382

VBA

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

0グッド

0クリップ

投稿2018/01/10 09:02

お疲れ様です。

配列格納時に重複チェックを行いデータ格納を行うか、行わないかの判断をしたいです。

下記エクセルのシートがあるとします。

A列,B列,C列,D列,E列,F列,G列,H列
――――――――――――――
性別,頭,鼻,耳,目,手,口,足
男A-○,○,○,○,,,○,○
男B-○,○,○,,,○,○,○
男C-○,○,○,,,○,○,○
男D-,○,○,,,○,○,○
女A-○,,,,,,○,○
女B-○,,,,,○,○,○
女C-○,,,,,○,○,○
女D-○,,,,,○,○,○

上記のデータを男、女でまとめ、それぞれ○がついているところのORをした結果のヘッダを格納したいです。
たとえば男の場合は、B列~H列では
○,○,○,,○,○,○となるので、
配列に「頭、鼻、耳、手、口、足」を男として格納し、下記になるよう格納

VBA

1Dim Hoge(1,7) As String 2Hoge(0,0) = "男" 3Hoge(0,1) = "頭" 4Hoge(0,2) = "鼻" 5Hoge(0,3) = "耳" 6Hoge(0,4) = "手" 7Hoge(0,5) = "口" 8Hoge(0,6) = "足" 9Hoge(0,7) = ""

女性の場合は

VBA

1Hoge(1,0) = "女" 2Hoge(1,1) = "頭" 3Hoge(1,2) = "手" 4Hoge(1,3) = "口" 5Hoge(1,4) = "足" 6Hoge(1,5) = "" 7Hoge(1,6) = "" 8Hoge(1,7) = "" 9

となるように格納します。

この時の条件として、下記のような実装をしているのですが、
コメントに記載されているような、重複データが格納されてしまうので、どのように回避すべきか悩んでおります。

VBA

1Dim i As Integer 2Dim j As Integer 3For i = 1 To 8 4 For J = 1 To 8 5 If Cells(i + 1,j + 1) = "○" Then 6 '配列格納処理を入れたいが、上の条件文だと、○が男A、男Bで被った場合、”頭”が二つ格納されてしまう。 7 End If 8 NEXT 9NEXT 10If Cells()

よろしくお願いいたします。

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

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

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

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

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

guest

回答4

0

重複チェックは Dictionary を使うと簡単です。
頑張ってください。

投稿2018/01/10 10:46

ExcelVBAer

総合スコア1175

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

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

0

ベストアンサー

簡単な方法

この処理で作成した配列をその後どう使いたいかによっても変わってきそうですが、一番お手軽な方法はakabeeさんから提示されているような、配列を上書きしていく方法だと思います。

ただし、この方法では配列Hogeの要素2のインデックスに対し、設定される項目内容が固定となります。
つまり
Hoge(n, 0) :性別
Hoge(n, 1) :頭
Hoge(n, 2) :鼻
Hoge(n, 3) :耳
Hoge(n, 4) :目
Hoge(1, 5) :手
Hoge(1, 6) :口
Hoge(1, 7) :足
となります。

例えば例文の女性の場合だと、
Hoge(1,0) = "女"
Hoge(1,1) = "頭"
Hoge(1,2) = ""
Hoge(1,3) = ""
Hoge(1,4) = ""
Hoge(1,5) = "手"
Hoge(1,6) = "口"
Hoge(1,7) = "足"
というように○のない項目は間が飛ぶような結果になりますので、配列から取り出す時には値の入っているものだけ取り出すような配慮が必要です。

別案

「私ならどう書くか」という観点からの別案として、ワークシート関数COUNTIFSを利用する方法をご紹介します。

範囲全体に対して、COUNTIFSで性別と各列で○がついている行数を判断し、配列に格納します。

COUNTIFSは条件に一致するセルの数を返してくれる関数です。

1つ目の条件として、対象範囲("A2:H9")のA列から、"男"(または"女")から始まるセルを判定しています。
2つ目の条件は列ループにより変動していきますが、対象範囲のB列以降を順番に処理していき、各列毎に値が"○"のセルを判定しています。

これら2つの条件を両方満たす行の数が返されることになるので、1行でも見つかればその性別で○のついている項目ということになりますので見出し文字列を配列に格納する、という流れになっています。

この方法であれば、行単位ではループせず、列ごとに合計行数で判別を行うため、重複を考慮する必要がありません。

Sub Sample() Dim Hoge(1, 8) As String Dim iIdx1 As Integer Dim iIdx2 As Integer Dim iCol As Integer Dim rng As Range Set rng = Range("A2:H9") '対象範囲 'あらかじめ性別を格納 Hoge(0, 0) = "男" Hoge(1, 0) = "女" For iIdx1 = 0 To 1 '要素1(性別)をループ iIdx2 = 1 '要素2のカウンタを初期化 For iCol = 2 To 8 'COUNTIFSでA列の性別と、対象列が○の行数をカウント。1行でも見つかれば見出し内容を配列に格納 If Application.WorksheetFunction.CountIfs(rng.Columns(1), Hoge(iIdx1, 0) & "*", rng.Columns(iCol), "○") > 0 Then Hoge(iIdx1, iIdx2) = Cells(1, iCol) iIdx2 = iIdx2 + 1 '要素2をカウントアップ End If Next Next End Sub

以上、参考になれば幸いです。

投稿2018/01/11 01:57

編集2018/01/11 05:38
jawa

総合スコア3013

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

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

King_of_Flies

2018/01/11 06:58

実データとフォーマットがまるきっり変更になったため、大分カスタマイズで手間取りましたが、 jawaさんのソースを参考に上手く動作するものが作れました。 ありがとう。
guest

0

ループの順番を逆にしたら楽だと思います。
現状だと、男Aについて頭・鼻~、の順で見ていますが、
頭について、男A・男B~で見ると良いです。

VBA

1Dim r As Integer ' 行カウンタ 2Dim c As Integer ' 列カウンタ 3Dim h(2) As Integer ' Hoge用カウンタ 4Dim Hoge(1, 7) As String 5 6' 要素0には男・女をあらかじめ入れておく 7Hoge(0, 0) = "男" 8Hoge(1, 0) = "女" 9 10' Hoge用のカウンタを初期化 11h(0) = 1 12h(1) = 1 13 14' 横方向のループ 15For c = 1 To 8 16 ' 男ループ 17 For r = 2 To 5 18 If Cells(r, c) = "○" Then 19 ' 配列に追加して 20 Hoge(0, h(0)) = Cells(1, c) 21 ' カウンタをインクリメント 22 h(0) = h(0) + 1 23 ' ループは抜ける 24 Exit For 25 End If 26 Next 27 ' 女ループ 28 For r = 6 To 9 29 If Cells(r, c) = "○" Then 30 Hoge(1, h(1)) = Cells(1, c) 31 h(1) = h(1) + 1 32 Exit For 33 End If 34 Next 35Next

男女の処理をひとつにまとめようかと思いましたが、複雑になりそうだったので分けました。

投稿2018/01/11 00:49

ttyp03

総合スコア16998

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

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

0

色々と方法はありそうですが、格納する場所が決まっているのであれば、配列にデータを「追加する」のではなく「上書きする」のではどうでしょうか。

以下のようにしてはいかがでしょう。(デバッグしていませんのであくまで参考にお願いします。)

VBA

1Dim i As Integer 2Dim j As Integer 3Dim Hoge(1,7) As String 4For i = 1 To 8 5 For J = 1 To 8 6 If Cells(i + 1,j + 1) = "○" Then 7 '配列の列番号の位置に、1行目の列の値を格納 8    'こうすれば値が重複することは無い 9 Hoge(j) = Cells(1,j + 1) 10 End If 11 NEXT 12NEXT 13If Cells() 14

男女のデータ格納を分ける場合は格納時の直前に条件分岐等を入れれば良いかと思います。

投稿2018/01/10 09:44

akabee

総合スコア1947

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問