[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『合計の検索』(ff)
例えば下記のように
A 1 1050 2 136 3 258 ○ 4 341 ○ 5 228 6 226 ○ 7 189 8 225 ○ 9 279 10 188
A1に合致する合計をA2〜A10のデータの中からピックアップ
する(○印)ことはできますか?
よろしくお願いいたします。
出来る自信も余り無いのですが、、、、 条件が後出しされるとつらいので先にお聞きします。
1.A2セル以下の実際のデータ量は何行くらいあるのですか?
2.A1セルの値にピッタリ合う組合せですね。 (出来るだけ近いもの、と云うようなアイマイなものではありませんね?)
3.何通りかの組合せがあったとしても、1種類だけでいいですね? (半平太)
提示のものだけでも別の組み合わせがありそうです。 マクロですが、これを実行すると、B列の2,3,7,9,10行目に○がつきます。 (ROUGE) '---- Sub test() Dim dic As Object, a, b As Long, i As Long, buf As String, j As Integer, x, r As Range ReDim a(1 To 2 ^ 9 - 1) For i = 1 To 2 ^ 9 - 1 For j = 1 To 9 If Val(Mid(Format(Val(Dec2(i)), "000000000"), j, 1)) = 1 Then buf = buf & " " & Range("A1").Offset(j).Value End If Next a(i) = Trim(buf) buf = "" Next Set dic = CreateObject("Scripting.Dictionary") For i = 1 To UBound(a) b = Evaluate(Replace(a(i), " ", "+")) dic(b) = a(i) Next If dic.Exists(Range("A1").Value) Then x = Split(dic(Range("A1").Value)) Else MsgBox "該当の組み合わせなし" Exit Sub End If Range("B2:B10").ClearContents For Each r In [A2:A10] If Not IsError(Application.Match(CStr(r.Value), x, 0)) Then r.Offset(, 1).Value = "○" End If Next End Sub Function Dec2(x As Long) As String Dim i As Long, n As Long, buf As Long n = x Do Until 2 ^ buf > n: buf = buf + 1: Loop For i = buf - 1 To 0 Step -1 If n >= 2 ^ i Then Dec2 = Dec2 & "1": n = n - 2 ^ i Else Dec2 = Dec2 & "0" End If Next End Function
Sub SAMPLE1() Dim I As Long For I = 2 To 1000 If (Cells(I, 1) = "") Then Exit For If (Cells(I, 2) = "○") Then Cells(1, 1) = Cells(1, 1) + Cells(I, 1) Next I End Sub
簡単に考えすぎて外してるのかなぁ "○"はB列と考えていいんですか?? (mr_mangoos)
mr_mangoosさん、入口と出口が反対でっせ。(ROUGE)
皆様ありがとうございます。思った以上に難しいんですね。
>半平太様 1.A2以下最高で50行です。30〜50の間です。 2.ピッタリ合わせたいです。 3.他の組み合わせもできるのであれば欲しいです。
>ROUGE様 テストしてみました。凄いです。 バッチリです。有難うございました。 偶然にも別の組み合わせができてしまいましたが、違う組み合わせ をC列にとかは可能なのでしょうか?いや考えて頂くほど滅多に あるとは思えませんのでこれで充分です。本当に助かりました。
>mr_mangoos様 有難うございます。説明が悪かったでしょうか? ROUGE様の仰るとおり、逆の操作が欲しかったです。
>1.A2以下最高で50行です。30〜50の間です。 しらみつぶしにチェックするロジックを考えていたのですが、 それでは事実上不可能な程の数です。
私は降りることにいたします。m(__)m (半平太)
50個のデータから3個を選択する場合 19,600通り
これらをすべて 計算することになります。
もう少しデータの割り振りを簡素化して 行数を少なくするようにしてみます。 有難うございました。 ff
諦めるのは未だ早い!(笑 こんな塩梅でどうでっか? 2個から5個まで全て組合せがB列以降に抽出されます。 (弥太郎) '---------------------- Sub f_f() Dim i As Long, y As Long, t As Long, f As Long, b As Long, j As Integer Dim flag As Boolean, tbl, fnd_count As Integer, m_row, data()
tbl = Cells(1, 1).Resize(Cells(Rows.Count, 1).End(xlUp).Row) On Error Resume Next fnd_count = StrConv(InputBox("何個でひろいまひょ?"), vbNarrow) If fnd_count = 0 Then Exit Sub Select Case fnd_count Case 2 For i = 2 To UBound(tbl, 1) If tbl(i, 1) < tbl(1, 1) Then For b = i + 1 To UBound(tbl, 1) If tbl(1, 1) = tbl(i, 1) + tbl(b, 1) Then j = j + 1 ReDim Preserve data(1 To UBound(tbl, 1), 1 To j) data(i, j) = "○" data(b, j) = "○" flag = True End If Next b End If Next i Case 3 For i = 2 To UBound(tbl, 1) - 1 If tbl(i, 1) < tbl(1, 1) Then For y = i + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) < tbl(1, 1) And UBound(tbl, 1) > y Then For b = y + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(b, 1) = tbl(1, 1) Then j = j + 1 ReDim Preserve data(1 To UBound(tbl, 1), 1 To j) data(i, j) = "○" data(y, j) = "○" data(b, j) = "○" flag = True End If Next b End If Next y End If Next i
Case 4 For i = 2 To UBound(tbl, 1) - 2 If tbl(i, 1) < tbl(1, 1) Then For y = i + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) < tbl(1, 1) Then For t = y + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) < tbl(1, 1) Then For b = t + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) + tbl(b, 1) = tbl(1, 1) Then j = j + 1 ReDim Preserve data(1 To UBound(tbl, 1), 1 To j) data(i, j) = "○" data(y, j) = "○" data(t, j) = "○" data(b, j) = "○" flag = True End If Next b End If Next t End If Next y End If Next i Case 5 For i = 2 To UBound(tbl, 1) - 3 If tbl(i, 1) < tbl(1, 1) Then For y = i + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) < tbl(1, 1) Then For t = y + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) < tbl(1, 1) Then For f = t + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) + tbl(f, 1) < tbl(1, 1) Then For b = f + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) + tbl(f, 1) + tbl(b, 1) = tbl(1, 1) Then j = j + 1 ReDim Preserve data(1 To UBound(tbl, 1), 1 To j) data(i, j) = "○" data(y, j) = "○" data(t, j) = "○" data(f, j) = "○" data(b, j) = "○" flag = True End If Next b End If Next f End If Next t End If Next y End If Next i End Select If Not flag Then MsgBox "その個数での組合せは不可能です!": Exit Sub If j > 255 Then MsgBox "組合せが多すぎて表示でけまへん!": Exit Sub Cells(1, 2).Resize(UBound(tbl, 1), j) = data On Error GoTo 0
End Sub
弥太郎様 いいもの頂きまして有難うございます。 頂いておいて恐縮ですが、現時点では、個数を限定させる のは作業上少し手間かなと思います。(ページ数が多い) でもこの構文、他の利用法が即座に浮かびましたので 思いっきり使わせていただきます。また躓きましたら ご教授願います。 感謝。 ff
諦めるのはまだ早い!(笑 ほならこれどうでっか? 2個から5個までの全ての組合せを抽出します。 勿論抽出個数指定無しでデスヨ。 (弥太郎) '----------------------- Sub f_f2() Dim i As Long, y As Long, t As Long, f As Long, b As Long, j As Integer Dim flag As Boolean, u As Integer, tbl, data()
tbl = Cells(1, 1).Resize(Cells(Rows.Count, 1).End(xlUp).Row) On Error Resume Next For u = 2 To 5 Select Case u Case 2 For i = 2 To UBound(tbl, 1) If tbl(i, 1) < tbl(1, 1) Then For b = i + 1 To UBound(tbl, 1) If tbl(1, 1) = tbl(i, 1) + tbl(b, 1) Then j = j + 1 ReDim Preserve data(1 To UBound(tbl, 1), 1 To j) data(i, j) = "○" data(b, j) = "○" flag = True End If Next b End If Next i Case 3 For i = 2 To UBound(tbl, 1) - 1 If tbl(i, 1) < tbl(1, 1) Then For y = i + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) < tbl(1, 1) And UBound(tbl, 1) > y Then For b = y + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(b, 1) = tbl(1, 1) Then j = j + 1 ReDim Preserve data(1 To UBound(tbl, 1), 1 To j) data(i, j) = "○" data(y, j) = "○" data(b, j) = "○" flag = True End If Next b End If Next y End If Next i
Case 4 For i = 2 To UBound(tbl, 1) - 2 If tbl(i, 1) < tbl(1, 1) Then For y = i + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) < tbl(1, 1) Then For t = y + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) < tbl(1, 1) Then For b = t + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) + tbl(b, 1) = tbl(1, 1) Then j = j + 1 ReDim Preserve data(1 To UBound(tbl, 1), 1 To j) data(i, j) = "○" data(y, j) = "○" data(t, j) = "○" data(b, j) = "○" flag = True End If Next b End If Next t End If Next y End If Next i Case 5 For i = 2 To UBound(tbl, 1) - 3 If tbl(i, 1) < tbl(1, 1) Then For y = i + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) < tbl(1, 1) Then For t = y + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) < tbl(1, 1) Then For f = t + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) + tbl(f, 1) < tbl(1, 1) Then For b = f + 1 To UBound(tbl, 1) If tbl(i, 1) + tbl(y, 1) + tbl(t, 1) + tbl(f, 1) + tbl(b, 1) = tbl(1, 1) Then j = j + 1 ReDim Preserve data(1 To UBound(tbl, 1), 1 To j) data(i, j) = "○" data(y, j) = "○" data(t, j) = "○" data(f, j) = "○" data(b, j) = "○" flag = True End If Next b End If Next f End If Next t End If Next y End If Next i End Select Next u If Not flag Then MsgBox "その個数での組合せは不可能です!": Exit Sub If j > 255 Then MsgBox "組合せが多すぎて表示でけまへん!": Exit Sub Cells(1, 2).Resize(UBound(tbl, 1), j) = data On Error GoTo 0
End Sub
データが23個までの制限付きですが、改訂しました。 このロジックだと、データがひとつ増えるごとにおよそ2倍の時間がかかるようになりそうです。。。 (ROUGE) '---- Sub test() Dim dic As Object, tbl, a(), x Dim i As Long, j As Integer, n As Integer, b As Long Dim buf As String With Range("A2", Range("A" & Rows.Count).End(xlUp)) If .Rows.Count > 23 Then MsgBox "これ以上は能力の限界です。。。", vbExclamation Exit Sub End If tbl = .Value n = .Rows.Count End With ReDim a(1 To 2 ^ n - 1) For i = 1 To 2 ^ n - 1 buf = Dec2(i) buf = String(n - Len(buf), "0") & buf a(i) = buf buf = "" Next Set dic = CreateObject("Scripting.Dictionary") For i = 1 To UBound(a) For j = 1 To n If Val(Mid(a(i), j, 1)) = 1 Then buf = buf & " " & tbl(j, 1) End If Next buf = Replace(Trim(buf), " ", "+") b = Evaluate(buf) buf = "" If dic.Exists(b) Then x = dic(b) ReDim Preserve x(UBound(x) + 1) x(UBound(x)) = a(i) dic(b) = x Else dic(b) = Array(a(i)) End If Next Range("B2", Cells(n + 1, Columns.Count)).ClearContents If Not dic.Exists(Range("A1").Value) Then MsgBox "該当の組み合わせはありませんでした。。。" GoTo errhdl End If x = dic(Range("A1").Value) For i = LBound(x) To UBound(x) If i + 1 > Columns.Count Then MsgBox "これ以上の組み合わせがありますが、表示できません。。。" GoTo errhdl End If For j = 1 To Len(x(i)) If Val(Mid(x(i), j, 1)) = 1 Then Range("B1").Offset(j, i).Value = "○" End If Next Next errhdl: Set dic = Nothing Erase tbl, a End Sub Function Dec2(x As Long) As String Dim i As Long, n As Long, buf As Long n = x Do Until 2 ^ buf > n: buf = buf + 1: Loop For i = buf - 1 To 0 Step -1 If n >= 2 ^ i Then Dec2 = Dec2 & "1": n = n - 2 ^ i Else Dec2 = Dec2 & "0" End If Next End Function
ししょ〜の試しましたが、速いですね〜。 でもプロシジャ名が予約語に当たるみたいなので、変更した方がよさそうです。
あ、ほんまや(汗 HNをそのままマクロ名にしてしまうクセがついとるもんで、つい^^ 変更しときますた〜。 (弥太郎)
(ROUGE)
>弥太郎様 めちゃめちゃ早いです。成せばなる域に達するのは 自分には到底無理ですね。勉強不足で改造に苦しんでおりますので、 このまま使用させていただきます。有難うございました。
>ROUGE様 パソコンが考え込んでしまってそのまま眠りました。 コピペが悪いのかなぁ??EXCELがもう1個起動します。??? 時間とらせて申し訳ありませんでした。 ff
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.