"3種の板があります。 板の巾はWaミリ、Wbミリ、Wcミリです。 同じ巾の板は5枚まで使える事とします。 全ての板の組み合わせをワークシートsh1のA1から書き出す事とします。 また、表記はWaX1、WbX0、WcX5 という風にします。下記コードで動くのですが、板の種類や、同じ板を使える枚数を増やすと、シートへの書き出し時間が何時間も掛かってしまいます。下記コードを配列に直していただけないでしょうか。私は配列が苦手なものですので。
Sub 全ての板の組み合わせを書き出す()
Dim Wa As Integer, Wb As Integer, Wc As Integer '板の巾
Dim i As Integer, j As Integer, k As Integer 'カウンター変数
Sheets(""sh1"").Range(""A1"").Value = ""組み合わせ"" '表の見出しを書き出す
'すべての板の組み合わせを書き出す
For i = 0 To 5 'Waの板の数を0から5まで変化させる
For j = 0 To 5 'Wbの板の数を0から5まで変化させる
For k = 0 To 5 'Wcの板の数を0から5まで変化させる
Sheets(""sh1"").Range(""A"" & Rows.Count).End(xlUp).Offset(1, 0).Value = _
""Wa"" & ""x"" & i & "", Wb"" & ""x"" & j & "", Wc"" & ""x"" & k '組み合わせを書き出す
Next k
Next j
Next i
End Sub"
No.3ベストアンサー
- 回答日時:
こんにちは
単に組み合わせを書き出しているだけのようですが、この処理自体に意味があるのかどうかも疑問ですね。
板の種類をm、枚数上限をnとするなら、0枚を含めた場合、一般的にその組み合わせ数は (n+1)^m になります。
ご提示の3種類の場合で、99枚を超えると1列には表示しきれなくなりますね。
仮に3種類で99枚としても、100万回の計算になるのでそれなりの時間が掛かります。
配列を利用した場合、ご提示の方法よりはかなり速くなることは期待できますが、VBAそのものが決して速くはありませんので、ある程度の時間はかかります。
>下記コードで動くのですが、~
クォーテーションがおかしいようで、私の環境では動作しません。
以下、3種類限定で枚数に関しては可変にしてみましたが、私の環境では上限99枚の場合で、4~5秒程掛かりました。
(時間はPCの性能に依存しますので、あくまでも参考です。)
種類数も可変にしたければ、値を再帰的に作成すればできると思いますが、すぐにオーバーブローしそうなのと、処理そのものに意味があるとも思えないので省略します。
※ アクティブシートのA列に書き出しますのでご注意。
Sub 全ての板の組み合わせを書き出す()
Dim a, b, c, cnt, v
Const n = 9 ' ← 枚数上限
If n > 99 Then MsgBox "一列に入らない": Exit Sub
cnt = 2
Columns(1).ClearContents
v = Columns(1).Value
For a = 0 To n
For b = 0 To n
For c = 0 To n
v(cnt, 1) = "Wa×" & a & ",Wb×" & b & ",Wc×" & c
cnt = cnt + 1
Next c
Next b
Next a
v(1, 1) = "組み合わせ"
Columns(1).Value = v
End Sub
※ 勝手にな想像をすると、「目的とする幅に近い組み合わせを求めたい」のではないかと思いますが、以前のご質問でも回答したようにエクセルのソルバー機能を利用するのが簡単だと思います。
(VBAをいじくる必要も生じませんので)
https://oshiete.goo.ne.jp/qa/13440077.html
配列のご提示ありがとう御座いました。
そして、私のコードがWクォーテーションがおかしくなっていまして申し訳ありませんでした。
nを99(同じ種類の板を使える最大枚数)にして私のコードで実行すると、18分16秒。ご提示いただいた配列で実行するとなんと3秒で稼働出来ました。
なお、エクセルのソルバー機能は使った事がないのですが、これを機会に使ってみます。エクセルより早く稼働させるには、Pythonで計算させて、エクセルに出力させるという事になるのでしょうね。
No.4
- 回答日時:
No3です。
以前のご質問でも、今回でもなさりたいことが明確には示されていないので、よくわからないのですが・・・
>エクセルのソルバー機能は使った事がないのですが、これを機会に使ってみます。
ソルバーでは複数解を得ることはできませんが、以前の回答でも述べたように組み合わせを選定するにしても、実際には「最小値」だけが判断根拠ではないのではと想像します。
よくわからないので、勝手な想像で、
「目的の幅を数種類の板で埋める際の余りの少ない組み合わせを求めたい」
ということだと仮定すれば、添付図のような方法も考えられます。
・B1に目標とする幅
・B2にピックアップする条件
(成り行きで、最小板幅×係数としましたが、添付図の場合 180×0.5=90以下となる組み合わせをピックアップします)
・A~C列5行目以降に、使用できる板と幅、枚数上限(個別に指定)を入力
(図のWc、We、Wfのように幅、枚数が0あるいは空白の場合、不使用と判断します)
上記の条件で計算し、解となる組み合わせをE列以降にピックアップしています。
例示の場合は、条件に該当する組み合わせは12組で、5行目以降にその組み合わせと残余(=超過寸法)を列挙しています。
図からもわかるように、この場合には最小値(たまたまピッタリで0ですが)となる組み合わせが2組あることが示されています。
※ 「埋める」のが目的なので、「少しだけ足りない」組み合わせは無視しています。
※ A:C列とE列以降で、縦横を変えてしまいましたが、揃えておいた方が見やすいかも知れません。
なんとなく、数が増加する方向を下方向にしてしまったため、表示内容を入れ替えることになってしまいましたが・・・
なさりたいこと自体が「当たるも八卦」の想像なので、詳細は省きますが、方法としては以前の回答に記した通りの方法です。
なお、
>エクセルより早く稼働させるには、Pythonで計算させて、
>エクセルに出力させるという事になるのでしょうね。
計算量にもよりますが、総当たりで組み合わせを計算する方法をとるのならそうかもしれません。
とはいえ、前回回答にも示したように「目標幅/板幅」で当たりを付けることにより、無駄な組み合わせを相当に省くことが可能なはずですので、効率の良いロジックを採用することの方が、手段(=言語)を変える事よりも遥かに効果的と思います。
※ 勝手な想像ですので、ご参考にもならないのかも知れませんが、「こんなのもあり得るよ」という一例までに。
No.2
- 回答日時:
No1です。
失礼しました。
「提示されたマクロをコピペしてこちらで実行しようとするとエラーになってしまします。」
は
「提示されたマクロをコピペしてこちらで実行しようとするとエラーになってしまいました。」
の誤りです。訂正いたします。
No.1
- 回答日時:
提示されたマクロをコピペしてこちらで実行しようとするとエラーになってしまします。
あなたが実際に実行してきちんと動作しているマクロを提示していただけませんでしょうか。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) 稀に1円合いません? Sheet1から金額と個数を貼り付ける下記コードで、金額を切り上げるコードを何 3 2022/09/05 15:11
- Visual Basic(VBA) VBA Userformで一部別シートに転記がしたいのですが 2 2023/05/24 13:08
- Excel(エクセル) VBAで組み合わせ算出やCOUNTIFSの処理を高速化したいです。 4 2022/04/07 02:38
- Visual Basic(VBA) マクロ実行時、自動で背景色を変えたい。 C列にあるチェックボックスをチェックするとB列に「TRUE」 4 2022/11/08 11:14
- Visual Basic(VBA) エクセル マクロ(A1:A10)までの中で一番多く出た数字をB10に表示 6 2023/04/25 17:01
- Visual Basic(VBA) 2つ目のコンボボックスが動作しません。 3 2023/03/25 12:29
- Visual Basic(VBA) 別シートのデータを参照して値を入れたい。 まとめデータシートのC列D列の値を商品一覧シートのコードが 7 2022/08/17 13:20
- Visual Basic(VBA) ①ExcelVBAでカレンダーを作り、別のユザーフォームで日付を入力したいのですがエラーになります。 1 2023/02/17 18:39
- Visual Basic(VBA) VBAが止まります。 2 2022/09/02 14:02
- Visual Basic(VBA) ExcelVBAに関する質問 3 2023/02/17 10:47
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VBA 変数名に変数を使用したい。
-
VBA フォルダ内のファイルを、...
-
VBScript で ADO Streamオブジ...
-
.NET 文字コードの変換
-
レコードセットの中身を配列に...
-
配列のペースト出力結果の書式...
-
DBから取得した値を配列へ代入する
-
配列の中の最大値とそのインデ...
-
VBAにて、配列のデータを一度に...
-
グラフの「項目軸ラベルに使用...
-
INPUT関数でのCSV読込がおかしい件
-
降順・昇順のやり方(初心者)
-
エクセルでXY座標に並べられた...
-
VB.NETの配列とArrayListについ...
-
Dir関数で読み取り順を操作でき...
-
free()関数の多用 と Segment...
-
VB.NETの配列にExcelから読み込...
-
C言語 ポインタと配列
-
8bitインデックス画像の入出力方法
-
Excel2010のinputboxで複数デー...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBA 変数名に変数を使用したい。
-
Excel2010のinputboxで複数デー...
-
vba フィルター 複数条件 3つ以...
-
C#でbyte配列から画像を表示さ...
-
配列のペースト出力結果の書式...
-
Dir関数で読み取り順を操作でき...
-
エクセルでXY座標に並べられた...
-
VBAで配列引数を値渡しできない...
-
C++で作成したDLLにVBAから配列...
-
構造体配列の特定のメンバーをF...
-
OutOfMemoryExceptionの回避策...
-
大量の変数を定義するにはどう...
-
VBAでMODE関数をつくる
-
VBScriptでCSVファイルを読み出...
-
定数配列の書き方
-
Segmentation Fault (メモリ制限?)
-
Excelのメモリ(配列)の上限は2G...
-
Redim とEraseの違いは?
-
CheckBoxの配列化
-
配列の中の最大値とそのインデ...
おすすめ情報