商品コード一覧表をVBA「エクセル2003」で作成したいのです。
2年ほど前に、このサイトで助けていただいたものです。
http://oshiete.goo.ne.jp/qa/7578507.html
↑前回のものを利用していたのですが、今回、改良を加えていただいたいのです。
改良点は2つです。
1)6面を12面に増やす。
2)重複の少ないもから優先して抽出できるように(当面は400個の予定)
(問題点)
現在は6面のうち5面が同じになってしまう時もあります。
できる限り、重複しないものから優先的に並べられるようにしたいと思っております。
どうかよろしくお願いいたします。
A 回答 (7件)
- 最新から表示
- 回答順に表示
No.1
- 回答日時:
Range("A1")にファイル名(Sheet1のA1セル)
Range("B1")に商品数(Sheet1のB1セル)
・エクセルシートのA列に、たてに4×12個を入力
セル( A3~ A6)にA面の色コード
セル( A8~A11)にB面の色コード
セル(A13~A16)にC面の色コード
セル(A18~A21)にD面の色コード
セル(A23~A26)にE面の色コード
セル(A28~A31)にF面の色コード
セル(A33~A36)にG面の色コード
セル(A38~A41)にH面の色コード
セル(A43~A46)にI面の色コード
セル(A48~A51)にJ面の色コード
セル(A53~A56)にK面の色コード
セル(A58~A61)にL面の色コード
と、しています。
CSVファイルはデスクトップに出力します。
Sub Test()
Dim ColData As Variant, fName As String
Dim myStr As String, myPath As String
Dim v(), i As Long, j As Long
fName = Range("A1").Value
ReDim v(1 To Range("B1").Value)
ColData = Range("A3:A61").Value
For i = 1 To UBound(v)
Do
myStr = コード作成(ColData)
For j = 1 To i
If v(j) = myStr Then myFlg = True
Next
If myFlg <> True Then
v(i) = myStr
Exit Do
End If
myFlg = False
Loop
Next
myPath = CreateObject("WScript.Shell").SpecialFolders("Desktop") & "\"
Open myPath & fName & ".csv" For Output As #1
For i = 1 To UBound(v)
Write #1, fName, v(i)
Next i
Close #1
MsgBox "完了!!", 64
End Sub
Function コード作成(ColData As Variant) As String
Dim ColCD As String
Dim i As Long, j As Long, k As Long
Dim n As Long
Randomize
For i = 1 To 12
n = Int(Rnd() * 4) + 1
j = (i - 1) * 5
ColCD = ColCD & ColData(n + j, 1)
Next
コード作成 = ColCD
End Function
ありがとうございます。早速作動させてみました。
すると「インデックスが有効範囲にありません。」というエラー表示がでました。
また、大変申し訳ないのですが、商品数の指定をシート上ではなく、VBAのプログラムの中で指定してしますことができますでしょうか。
よろしくお願いいたします。
No.2
- 回答日時:
Sheet2 を作るまでですが、以下でどうなりますか
Public Sub test()
Dim nTotal As Long
Dim sFileName As String
Dim vAry As Variant, vSub As Variant
Dim dic As Object, dicW As Object
Dim v As Variant, vW As Variant
Dim sS As String
Dim i As Long
With Worksheets("Sheet1")
nTotal = .Range("B1") '←商品数(Sheet1のB1セル)
sFileName = .Range("A1") '←ファイル名(Sheet1のA1セル)
vAry = Array("A3:A6", "A7:A10", "A11:A14", "A15:A18", _
"A19:A22", "A23:A26", "A27:A30", "A31:A34", _
"A35:A38", "A39:A42", "A43:A46", "A47:A52")
ReDim vSub(UBound(vAry))
For i = 0 To UBound(vSub)
vSub(i) = .Range(vAry(i))
Next
End With
Randomize
Set dic = CreateObject("Scripting.Dictionary")
Set dicW = CreateObject("Scripting.Dictionary")
While (dic.Count < nTotal)
sS = ""
dicW.RemoveAll
For Each v In vSub
vW = v(Int(UBound(v) * Rnd()) + 1, 1)
dicW(vW) = Null
sS = sS & vW
Next
If (dicW.Count > (UBound(vSub) + 1) \ 2) Then dic(sS) = Null
Wend
Set dicW = Nothing
With Worksheets("Sheet2")
.Cells.ClearContents
.Range("B1").Resize(dic.Count) = WorksheetFunction.Transpose(dic.Keys)
.Range("B1:B" & dic.Count).Sort Key1:=.Range("B1")
.Range("A1").Resize(dic.Count) = sFileName
End With
Set dic = Nothing
End Sub
概略説明
> vAry = Array("A3:A6", "A7:A10", "A11:A14", "A15:A18", _
部分では、各面の色を扱う範囲を指定しておきます
(同一列で:"A3:B4" とかは NG)
記述した分が面数になります(上記では12個記述しているので12面)
また、上記では各色4つで記述していますが、ある面は6色・・・でも構いません
dic は出来上がった商品コードを重複なしで格納していきます
> While (dic.Count < nTotal)
で、必要数になるまで繰り返します
dicW では、商品コードを作っていく間、使用した色を重複なしで格納していきます
各色の抽出は、
> vW = v(Int(UBound(v) * Rnd()) + 1, 1)
と、乱数で各面の色を扱う範囲から色を選びます
各面がどのように接しているかわからないので、以下単純に
> If (dicW.Count > (UBound(vSub) + 1) \ 2) Then dic(sS) = Null
で、商品コードを作った時の色数が、必要面数の半分より上なら商品コードとして格納します
(6面なら > 3 の判別になるので、色が2つなら商品コードとして格納しません)
(12面なら > 6 )
この辺りは調整してください
できあがったら、商品コードを Sheet2 の B 列に設定してソートします
A 列に、ファイル名を設定して Sheet2 が出来上がります
※ 12面の時、> 10 とかすると、色の設定状況にもよりますが、
商品コードが作られにくい状況になり、無駄にループ回数が多くなるかもしれません
最悪、無限ループとかに陥るかもしれません
※ 確認される時には、商品数を 10 とか小さいものからにしてください
ありがとうございます。早速作動させてみました。
すると「型が一致しません。」というエラー表示がでました。
シート1のA列に入力するデータは「文字列」になります。
説明不足でした。
申し訳ございません。
No.3
- 回答日時:
>すると「インデックスが有効範囲にありません。
」というエラー表示がでました。どの箇所で出たのか説明がないと今後、回答しかねます。
Sub Test()
Dim ColData As Variant, fName As String
Dim myStr As String, myPath As String
Dim v(), i As Long, j As Long
Dim myFlg As Boolean, kazu As Long
kazu = Val(InputBox("商品数を入力して下さい。", "商品数入力"))
If kazu = 0 Then
MsgBox "キャンセルもしくは、数字以外を入力されました。"
Exit Sub
End If
fName = Range("A1").Value
ReDim v(1 To kazu)
ColData = Range("A3:A61").Value
For i = 1 To kazu
Do
myStr = コード作成(ColData)
For j = 1 To i
If v(j) = myStr Then myFlg = True
Next
If myFlg <> True Then
v(i) = myStr
Exit Do
End If
myFlg = False
Loop
Next
myPath = CreateObject("WScript.Shell").SpecialFolders("Desktop") & "\"
Open myPath & fName & ".csv" For Output As #1
For i = 1 To UBound(v)
Write #1, fName, v(i)
Next i
Close #1
MsgBox "完了!!", 64
End Sub
Function コード作成(ColData As Variant) As String
Dim ColCD As String
Dim i As Long, j As Long, k As Long
Dim n As Long
Randomize
For i = 1 To 12
n = Int(Rnd() * 4) + 1
j = (i - 1) * 5
ColCD = ColCD & ColData(n + j, 1)
Next
コード作成 = ColCD
End Function
迅速な回答をいただきましてありがとうございます。
次の2点のことを可能にできますでしょうか。
(1)
できる限り、重複している色が少ないコードを作りたいと思っています。たとえば、作成する数を1,000個、その中から重複の割合が少ないものから順に400個抽出する。
最初にメッセージボックスで「作成数」と「抽出数」を入力してから作成する。
(2)
最後にCSVファイルで保存する時にメッセージボックスでファイル名を入力できるようにする。
どうかよろしくお願いいたします。
No.4
- 回答日時:
#2です
> 「型が一致しません。」というエラー表示がでました。
これだけでは何も特定・想定できません
どの様なデータで、どの様な範囲指定して、どこでエラーになったのか提示してください。
最低限確認した内容を提示しておくと
A3~A6 に、A1, A2, A3, A4
A7~A10 に、B1, B2, B3, B4
A1 に、ABCDEFG、B1 に 400
Array 設定部分を、奇数面、偶数面に以下の様な同じ範囲を指定
vAry = Array("A3:A6", "A7:A10", "A3:A6", "A7:A10", _
"A3:A6", "A7:A10", "A3:A6", "A7:A10", _
"A3:A6", "A7:A10", "A3:A6", "A7:A10")
この指定で、エラーなく動作しており、エラーを想定する事が出来ません
具体的な環境・設定の提示をお願いします。
#2の記述において、
> 現在は6面のうち5面が同じになってしまう時もあります。
の解釈に間違いがあったかもしれません
過去QAでの例では、各色は異なる名称になっているようでしたが、
「6面のうち5面が同じ」ということは、同じ色が含まれた範囲指定なのか・・・
というものを想定したものになっていました。
なので、色の数で判別するという単純なものにしてました。
視点を変えて、同じ見え方・・・・を考えてみるに(面の配置を考慮)
例えば、1色で2か所を塗る・・・・
6面の場合、
サイコロ(天井:1、右:2、上:3、左:5、下:4、底:6)で考えてみると
1-2、1-3、1-5・・・ 12通りは、転がれば同じもの
1-6、2-5、3-4 の3通りも転がれば同じもの
このような同じものは排除したい・・・・ってなことだったのでしょうか
2色の、また3色の・・・場合のパターンを羅列するのもしんどいので
何色になるのかわからないけど、6箇所のパターンをチェックしましょう・・・というのが今回
天井:1、底:6とした場合、
(2,3,5,4)(3,5,4,2)(5,4,2,3)(4,2,3,5)の順4つは転がれば同じでしょう
また、天井:2、底:5とした場合、
(1,4,6,3)(4,6,3,1)(6,3,1,4)(3,1,4,6)の順4つは転がれば同じでしょう
同様に、天井:3・・・・
VBA での記述では、
vCary = Array( _
Array(1, Array(2, 3, 5, 4), 6), _
Array(2, Array(1, 4, 6, 3), 5), _
Array(3, Array(1, 2, 6, 5), 4), _
Array(4, Array(1, 5, 6, 2), 3), _
Array(5, Array(1, 3, 6, 4), 2), _
Array(6, Array(2, 4, 5, 3), 1) _
)
とする事に、
各面の色を乱数で抽出しておいて、
Array(1, Array(2, 3, 5, 4), 6), _
の場合、(1,2,3,5,4,6)(1,3,5,4,2,6)(1,5,4,2,3,6)(1,4,2,3,5,6)
の4通りの順で商品コードを生成し、既に求めていたものかをチェック
これを
Array(6, Array(2, 4, 5, 3), 1) _
まで繰り返します。
最終的に生成していなかった商品コードだったら、格納していくように・・・
これは、6面での例になる?と思うので、12面の場合は応用してみてください
色数の判別だけであれば、#2のもので容易に何面でも・・・
Public Sub test2()
Dim nTotal As Long
Dim sFileName As String
Dim vAry As Variant, vSub As Variant
Dim vCary As Variant, vC As Variant
Dim dic As Object
Dim v As Variant, vW As Variant, vv As Variant
Dim sS As String
Dim i As Long
Dim iEcnt As Long
With Worksheets("Sheet1")
nTotal = .Range("B1") '←商品数(Sheet1のB1セル)
sFileName = .Range("A1") '←ファイル名(Sheet1のA1セル)
vAry = Array("A3:A6", "A7:A10", "A3:A6", "A7:A10", _
"A3:A6", "A7:A10")
vCary = Array( _
Array(1, Array(2, 3, 5, 4), 6), _
Array(2, Array(1, 4, 6, 3), 5), _
Array(3, Array(1, 2, 6, 5), 4), _
Array(4, Array(1, 5, 6, 2), 3), _
Array(5, Array(1, 3, 6, 4), 2), _
Array(6, Array(2, 4, 5, 3), 1) _
)
ReDim vSub(UBound(vAry))
ReDim vC(UBound(vAry))
For i = 0 To UBound(vSub)
vSub(i) = .Range(vAry(i))
Next
End With
Randomize
Set dic = CreateObject("Scripting.Dictionary")
iEcnt = 0
Do While ((dic.Count < nTotal) And (iEcnt < 10000))
For i = 0 To UBound(vSub)
vC(i) = vSub(i)(Int(UBound(vSub(i)) * Rnd()) + 1, 1)
Next
For Each v In vCary
For Each vW In AryOrder(v)
sS = ""
For Each vv In vW
sS = sS & vC(vv - 1)
Next
If (dic.Exists(sS)) Then Exit For
Next
If (Not IsEmpty(vW)) Then Exit For
Next
If (IsEmpty(vW)) Then dic(Join(vC, "")) = Null
iEcnt = iEcnt + 1
Loop
Debug.Print iEcnt
With Worksheets("Sheet2")
.Cells.ClearContents
.Range("B1").Resize(dic.Count) = WorksheetFunction.Transpose(dic.Keys)
.Range("B1:B" & dic.Count).Sort Key1:=.Range("B1")
.Range("A1").Resize(dic.Count) = sFileName
End With
Set dic = Nothing
End Sub
Private Function AryOrder(vSrc As Variant) As Variant
Dim vAry As Variant, vS As Variant
Dim i As Long, j As Long, iPos As Long
ReDim vS(UBound(vSrc) + UBound(vSrc(1)))
ReDim vAry(UBound(vSrc(1)))
For i = 0 To UBound(vAry)
vS(0) = vSrc(0)
j = i
iPos = 1
While (iPos <= UBound(vSrc(1)) + 1)
vS(iPos) = vSrc(1)(j)
j = j + 1
If (j > UBound(vSrc(1))) Then j = 0
iPos = iPos + 1
Wend
vS(iPos) = vSrc(2)
vAry(i) = vS
Next
AryOrder = vAry
End Function
No.5
- 回答日時:
#4です
> 現在は6面のうち5面が同じになってしまう時もあります。
の解釈に間違いがあったと思います。
色の重複と思っていましたが、1面以外の色パターンが同じなんですよね
12面の時には、何面分で重複とみなすんでしょうか。
重複の排除は別のアプローチになると思います。
失礼しました
お世話になっております。以下、回答いたします。
12面文のコードを作成するには、
A面はA1~A4の4色から1つを選択
B面はB1~B4の4色から1つを選択
C面はC1~C4の4色から1つを選択
・
・
L面はL1~L4の4色から1つを選択
それぞれ選択した12個の色コードを1行に横に並べたものが商品コードです。
例えば、
1)A1B1C1D1E1F1G1H1I1J1K1L1
2)A1B2C1D2E1F2G1H2I1J2K1L2
3)A1B2C3D4E1F2G3H4I1J2K3L4
このような商品コードになります。
重複の度合いを見てみると・・・
1)と2)では、6個の重複があります。
(具体的には、A1、C1、E1、G1、I1、K1の6個)
1)と3)では、3個の重複があります。
(具体的には、A1、E1、I1の3個)
2)と3)では、6個の重複があります。
(具体的には、A1、B2、E1、F2、I1、J2の6個)
以前のプログラムでは、以下のように12個のうち11個までが重複している場合もありました。
1)A1B1C1D1E1F1G1H1I1J1K1L1
2)A2B1C1D1E1F1G1H1I1J1K1L1
↑1面目のA1とA2以外はすべて同じになっています。
> 12面の時には、何面分で重複とみなすんでしょうか。
> 重複の排除は別のアプローチになると思います。
ここから、上のご質問の回答になりますが・・・
重複とみなさないとするのは「○面」という決まったものは無いのですが、
出来る限り、重複の少ないものを400個作成したいと考えております。
素人考えですが、
2,000とか3,000と多めに作って、重複の少ない順に400個を選び出す。
というような方法はできますでしょうか。
「追記」
♯4のプログラムは問題なく動作いたしました。大変ありがとうございました。
しかし、1つ1つの色コードが2文字3文字程度であれば問題なく動作するのですが、
色コードの文字数を50文字とか60文字にすると、「型が一致しません。」というメッセージが表示されません。
エラーメッセージのウィンドウが出るだけで、どの行がエラーなのか表記がどこにも出ていません。
「用いたデータ」
商品コード 400
色コードA1色コードA2色コードA3色コードA4色コードA5色コードA6色コードA7色コードA8色コードA9
色コードB1色コードB2色コードB3色コードB4色コードB5色コードB6色コードB7色コードB8色コードB9
色コードC1色コードC2色コードC3色コードC4色コードC5色コードC6色コードC7色コードC8色コードC9
・
・
・
色コードJ1色コードJ2色コードJ3色コードJ4色コードJ5色コードJ6色コードJ7色コードJ8色コードJ9
色コードK1色コードK2色コードK3色コードK4色コードK5色コードK6色コードK7色コードK8色コードK9
色コードL1色コードL2色コードL3色コードL4色コードL5色コードL6色コードL7色コードL8色コードL9
「用いた範囲指定」
vAry = Array("A3:A6", "A7:A10", "A11:A14", "A15:A18", _
"A19:A22", "A23:A26", "A27:A30", "A31:A34", _
"A35:A38", "A39:A42", "A43:A46", "A47:A50")
上記の色コードで作成すると、できるであろう商品コードは、54文字×12面=648文字となります。
最大でこの位のコードを作成できるようにしたいのですが、不可能なのでしょうか。
(2年前にご教示いただいたプログラムでは、600~800文字でも動作しております。)
No.6
- 回答日時:
これでどうかな
Sub TestMyXXX()
Dim i As Long, j As Long
Dim myDic As Object, myDicKey
Dim myArray(1 To 12) As String
Dim myTemp As String
Dim sFileName As String
Set myDic = CreateObject("Scripting.Dictionary")
Do While myDic.Count < 400
Do
For i = 1 To 12
myArray(i) = Chr(64 + i) & Int(Rnd() * 4) + 1
Next i
myTemp = Join(myArray, "")
'同じ数字が、6個以上あればやり直し
'24(myTempの文字数)-6 < 19
If Len(Replace(myTemp, "1", "")) < 19 Then
ElseIf Len(Replace(myTemp, "2", "")) < 19 Then
ElseIf Len(Replace(myTemp, "3", "")) < 19 Then
ElseIf Len(Replace(myTemp, "4", "")) < 19 Then
'同じ組み合わせが、以前にあればやり直し
ElseIf myDic.exists(myTemp) Then
Else
myDic(myTemp) = myTemp
Exit Do
End If
Loop
Loop
myDicKey = myDic.keys
With Sheets("Sheet1")
.Cells.ClearContents
.Cells(1, 1).Resize(myDic.Count) = WorksheetFunction.Transpose(myDicKey)
.Copy
End With
sFileName = "Tset" & Format(Now, "yyyymmddhhmmss")
ActiveWorkbook.SaveAs Filename:=ThisWorkbook.Path & "\" & sFileName, FileFormat:=xlCSV
ActiveWindow.Close (False)
Set myDic = Nothing
End Sub
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
フィルターかけた後、重複を除...
-
COBOLの文法
-
Exel VBA 別ブックから該当デ...
-
1日に1人がこなせるプログラム...
-
2つのチェックボックスを制御
-
Nullの使い方が不正です。
-
ペンダントライトのコードの色...
-
VBA 現在のセル番地を記憶、復...
-
access2003 クエリSQL文に...
-
access2021 VBA メソッドまたは...
-
VLookup関数を使ってラベルに表...
-
ブログ等で公開されているサン...
-
ACCESSユニオンクエリでORDER B...
-
SQL
-
VBA・VB6.0・VB.NETの文字列型
-
VB6.0 コンボBOXから...
-
ゲームのアルゴリズム
-
VBAでxmlから特定の文字を変数...
-
1、Rstudioで回帰直線を求める...
-
オートフィルタで抽出結果に 罫...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
フィルターかけた後、重複を除...
-
JANコードとPOSコードは同じ?
-
access2003 クエリSQL文に...
-
1日に1人がこなせるプログラム...
-
オートフィルタで抽出結果に 罫...
-
変数名「cur」について
-
JavaScriptの定数名が取り消し...
-
ACCESSユニオンクエリでORDER B...
-
Exel VBA 別ブックから該当デ...
-
UWSCでMOUSEORG関数が上手く処...
-
COBOLの文法
-
PreviewKeyDownイベントが2回...
-
1、Rstudioで回帰直線を求める...
-
VBAでファイルオープン後にコー...
-
【VB6】実行ファイルとした後、...
-
Nullの使い方が不正です。
-
特定行の背景色を変えたいのですが
-
◾️Excel VBA 統合について Cons...
-
アルファベットに付いて質問し...
-
Excel VBAでOpenTextのFieldInf...
おすすめ情報