• ベストアンサー

要素数未定の2次元配列について

【開発環境】VB6_SP5  OS:WinXP 非常に困っています。どうかご教示お願い致します。 コマンドボタンを押す度に、そのフォームのデータ(Text(n).Text)を 2次元配列に格納したいのですが、コマンドボタンを押す度にReDimを 通過するため、前に格納したデーター「配列名(0,0)等」が消えてしまいます。 Publicで使える様に配列HairetsuA~Cについて、何かよい知恵はありませんか? Option Explicit Public Const YousoMax = 10 Public HairetsuA() As String Public HairetsuB() As String Public HairetsuC() As String Public YousoA as Integer -------------------------------------------------- Private Sub Command1_Click() Dim YousoB As Integer ReDim HairetsuA(YousoA, YousoB) As String ReDim HairetsuB(YousoA, YousoB) As String ReDim HairetsuC(YousoA, YousoB) As String    For YousoB = 0 To YousoMax       If Form1.Text1.Text <> "" Then          ReDim Preserve HairetsuA(YousoA, YousoB) As String          ReDim Preserve HairetsuB(YousoA, YousoB) As String          ReDim Preserve HairetsuC(YousoA, YousoB) As String          HairetsuA(YousoA, YousoB) = Form1.Text1.Text          HairetsuB(YousoA, YousoB) = Form1.Text2.Text          HairetsuC(YousoA, YousoB) = Form1.Text3.Text       Else          Exit For       End If    Next    YousoA = YousoA + 1 End Sub 分かり難い説明ですが、HairetsuAだけを取って言葉で説明しますと コマンドボタンを押す度に HairetsuA(0,0)にはアイウエオ HairetsuA(0,1)にはカキクケコ HairetsuA(0,2)にはサシスセソ    ・    ・    ・ HairetsuA(0,n)にはラリルレロ (コマンドボタンを押す) (HairetsuA(0,0)~HairetsuA(0,n)のデータは維持したままで) HairetsuA(1,0)にはABCDE HairetsuA(1,1)にはFGHIJ HairetsuA(1,2)にはKLMNO    ・    ・    ・ HairetsuA(1,n)にはVWXYZ    ・ (途中幾度かコマンドボタンを押下) (HairetsuA(0,0)~HairetsuA(n-1,n-1)のデータは維持したままで)    ・ HairetsuA(n,n)にはチリヌルオ どうか良いお知恵をください。 どうぞ宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • pulsa
  • ベストアンサー率57% (34/59)
回答No.2

ちょっとメンドクサイ&難しいですが、ジャグ配列にしてはいかがでしょう HairetsuA(YousoA)(YousoB) ってな感じで使います 説明用にあえてイモく書いている部分があります Option Explicit Const YousoMax = 10 Public HairetsuA Public HairetsuB Public HairetsuC Public YousoA As Integer Private Sub Command1_Click()   Dim YousoB As Integer   Dim bufHairetsuA   Dim bufHairetsuB   Dim bufHairetsuC      If YousoA = 0 Then     ReDim HairetsuA(0)     ReDim HairetsuB(0)     ReDim HairetsuC(0)   Else     ReDim Preserve HairetsuA(YousoA)     ReDim Preserve HairetsuB(YousoA)     ReDim Preserve HairetsuC(YousoA)   End If      ReDim bufHairetsuA(0)   ReDim bufHairetsuB(0)   ReDim bufHairetsuC(0)   For YousoB = 0 To YousoMax     If YousoB > 0 Then '変数がEmptyの時Preserve 出来ない対応       ReDim Preserve bufHairetsuA(YousoB)       ReDim Preserve bufHairetsuB(YousoB)       ReDim Preserve bufHairetsuC(YousoB)     End If     If Form1.Text1.Text <> "" Then        bufHairetsuA(YousoB) = Form1.Text1.Text '格納用配列に追加        bufHairetsuB(YousoB) = Form1.Text2.Text '格納用配列に追加        bufHairetsuC(YousoB) = Form1.Text3.Text '格納用配列に追加     Else        Exit For     End If   Next   HairetsuA(YousoA) = bufHairetsuA  '配列書き出し   HairetsuB(YousoA) = bufHairetsuB  '配列書き出し   HairetsuC(YousoA) = bufHairetsuC  '配列書き出し   YousoA = YousoA + 1 End Sub End Subにブレイクを置いて実行して見て下さい ウォッチウィンドウにHairetsuAなどを入れて見れば大体判るかと思います 簡単に説明すると、配列を配列に叩き込みます コレはVariant型が何でも入る事を利用しています 相当なメモリを消費しますので、思ったより拡張できないかもしれません >HairetsuA(n,n)にはチリヌルオ は HairetsuA(n)(n)にはチリヌルオ となります エクセルVBAでしか試してない(WinXP Excel2003)ので、微妙に違うかも… がんばってねぇ~(^^)/~

Project_D
質問者

お礼

pulsa様 おはようございます。早々のご回答ありがとうございました。 しかも実はこっそり望んでおりました、サンプルコードまで書いて頂き とても感謝致します。 当方も早速、ジャグ配列のコーディングを行いました。 結果、無事に思う様に各要素が各配列に格納できました。 このジャグ配列とは多段配列とはまた違うんですね! もっぱら多段配列も使ったことないのですが・・・(^^;A redfox63様の回答レスにも書かせて頂きましたが、私の思い込みで ReDim Preserveは全次元を変更出来ると言う雄大なものでした(^^;A 本当に助かりました。ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (1)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

この仕様だと無理があると思いますよ 内容を保持したままにする場合 Preserveを使いますがこの場合は 最後の次元の添え字は変更出来ますが、それ以外を変更しようとするとError9が発生します 今回の場合なら YousoAは固定になり、YousoBはReDimで変更可能です しかし ReDim Preserve HairetsuA( 3, 2 ) を実行してから ReDim Preserve HairetsuA( 3, 1 )を実行してしまうと前回代入した HairetsuA( 3, 2 )の要素は破棄されてしまいます さほど大きくないデータなら 余裕を見て宣言しましょう または、1次元目を10固定にして、2次元目YousoAで拡張していくように変更してみましょう HairetsuA( 0, 0 ) = アイウエオ HairetsuA( 1, 0 ) = カキクケコ HairetsuA( 2, 0 ) = サシスセソ ... 次回は HairetsuA( 0, 1 ) = ABCDE HairetsuA( 1, 1 ) = FGHIJ HairetsuA( 2, 1 ) = KLMNO といった具合にしてやれば 要求を満たせそうですよ これなら ReDim Preserve HairetsuA( 10, YousoA ) で拡張でき以前のデータも消えることがありません

Project_D
質問者

お礼

redfox63様 早速のご回答ありがとうございました。 カンマ切りのcsvファイルの読み込み等でRedimとPreserveを幾度か 使って来てきました。 今回の問題があってヘルプを開いて該当部分を見たのですが、 一番大事な「最後の次元の添え字は変更出来ます」の『最後の添え字』を すっかり見落としてしていました。 Max32次元まであらゆるパターンに対応出来る魔法のステートメントだと 思ってました。 でも今回はクライアントがYousoAを幾らまでするかが全く不明で 予め決めるのは無理そうです。 なので今回はpulsa様のジャグ配列に挑戦してみようと思います。 しかし『最後の添え字』について思い違いの払拭と、早々のご回答に とても感謝いたします。ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • AccessVBAで、二次元配列を動的に設定したい

    以下のコードにあるattrという配列に、DB上のとあるコードと名前を設定したいと思います。 DB上のデータ量は可変なので、データを取得するごとに動的に配列attrの要素数を動的に増やしたいと思っています。 検索等で色々と調べながら以下のコードを書いてみたのですが、どうもうまく動きません。 ご教授願います。 --------------------------------------------------- Dim attr() As String [loop start] ReDim Preserve attr(i, 0) ReDim Preserve attr(i, 1) attr(i, 0) = コード attr(i, 1) = 名前 [loop end]

  • 配列の要素数について

    下記の記述の場合、配列の要素数っていくつになりますか? Dim strArray() As String ReDim strArray(0) また下記のように、配列の要素数を具体的に書かずに使った場合不具合はでますか? Dim strArray() As String strArray(0) = "aa" strArray(1) = "bb"

  • VB6で、一次元配列と二次元配列の相互コピー

    VB6で、一次元配列と二次元配列の相互コピーをしたいです。 (1)元々下記のような宣言をもつ配列がありました。 Public Type TKey no As String id As String code As String atr() As String End Type Public Type tr Key As TKey atr() As String abc As Boolean End Type Public gtr() As tr (2)コピー用に、下記のような二次元配列用宣言をつくりました。 Public Type TKey2 2no As String 2id As String 2code As String a2tr() As String End Type Public Type 2tr Key22 As TKey2 atr22() As String abc22 As Boolean End Type Public g2tr() As 2tr (3)  (1)から(2)にデータを複製したり、 (4)  (2)から(1)にデータを複製したいです。 今は、下記のように面倒くさいことをしています。 dim gtr(maxcnt) ReDim Preserve g2tr(500, maxcnt) ループ g2tr(cnt, i).Key22.2code = gtr(i).Key.code ・・・(3) gtr(i).Key.code = g2tr(j, i).Key22.2code ・・・(4)       今は上記を全ての宣言の配列に実行しています。 なにかもっと効率のよい方法はないでしょうか。 (1)の配列は、1~500くらいはあり、不定です。

  • VB 配列

    今,VBでテキストファイルを読込み配列に入れるという作業を書いたのですが,うまくいきません. 初回例外が発生してしまいます.配列は文字列の配列になります. どなたかご教示のほどよろしくお願いいたします. 'ファイルの読込み Dim path1 As String = "C:\Users\aleph_H.S\Desktop\気象台データインポートツール\気象台データインポートツール\" Dim path2 As String = "気象台データリスト.txt" Dim Mypath As String = path1 + path2 ' StreamReader の新しいインスタンスを生成する Dim cReader As New System.IO.StreamReader(Mypath, System.Text.Encoding.Default) ' 読み込んだ結果をすべて格納するための変数を宣言する Dim stResult As String = String.Empty Dim matrix(,) As String Dim ic As Long = 0 Dim icc As Long = 0 ReDim Preserve matrix(80, 3) ' 読み込みできる文字がなくなるまで繰り返す While (cReader.Peek() >= 0) ' ファイルを 1 行ずつ読み込む Dim stBuffer As String = cReader.ReadLine() ' 読み込んだものを追加で格納する stResult &= stBuffer & System.Environment.NewLine ic = ic + 1 'カンマ区切りで分割して配列に格納する Dim stArrayData As String() = stResult.Split(","c) For Each sstData In stArrayData icc = icc + 1 '文字列をInteger型に変換 matrix(ic - 1, icc - 1) = sstData Next End While cReader.Close()

  • 2次元配列について

    VB6.0で開発しています。 以前COBOLをしていて、VBではどのように定義するかがわからなかったので質問します! ----------- COBOL ----------------- 01 TBL-AREA. 03 TBL OCCURS 6. 05 TBL-IX OCCURS 16. 07 TBL-IX PIC 9(07). 07 TBL-NAME PIC N(20). と定義した場合はVBではどのように記述するのですか? Public Type TBL_AREA TBL_TEXT As Integer TBL_Caption As String End Type Public TBLArray() As TBL_AREA ReDim TBLArray(6,16) と記述してみたものはいいものの、処理の記述方法がわかりません(恥)

  • VBAの動的配列について

    いつもお世話になっております。 エクセルVBAを学習中の者です。 動的配列についてお伺いします。 添付資料を見て頂きたいのですが、 シート名1~4に同一レイアウトの表があります。 これらの表をを2次元配列に格納し、その後、同一レイアウトのシートに一括転記したいと考えています。 転記の事を考えて、条件としては、 シート1から2行目以降のデータを配列『data』に格納、変数『dataCnt』が転記先の行番号と同じになるように考えています。 当初は、配列の定義を『Dim data(100,3) As Variant』と、多めに要素数を定義して、コードを記述していました。 正直、凄く気持ちが悪い感じでした・・・ 最近、動的配列を学習しまして、 シートごとにデータの行数を変数『lastRow』に格納して、配列を再定義して【データ数=要素数】とならないか? と思い、下記のようなコードを書いてみました。 が、『ReDim Preserve~』で実行エラーが発生してしまいます。 原因がなぜかわかりません! そもそも、動的配列はこのような使い方は出来ないのでしょうか? Sub テスト() Dim data() As Variant Dim x As Long Dim i As Long Dim ii As Long Dim lastRow As Long Dim dataCnt As Long dataCnt = 2 For x = 2 To 5 Worksheets(x).Activate lastRow = Cells(Rows.Count, 1).End(xlUp).Row If x = 2 Then ReDim data(2 To lastRow, 3) Else ReDim Preserve data(2 To dataCnt + lastRow - 1, 3) End If For i = 2 To lastRow For ii = 1 To 3 data(dataCnt, ii) = Cells(i, ii) Next ii dataCnt = dataCnt + 1 Next i Next x End Sub どなたかご指導をよろしくお願いいたします。

  • C# 配列の配列(多次元配列?)

    C#において、配列の配列中に格納した値を、検索することを 行いたいのですが、格納した値そのものを見ることができません。 まだ、C#を始めて間もないので、配列に格納する時点で、 不備があるかも知れませんが、お願いします。 やりたいこと ・テキストファイル内にある値を、2次元配列または、多次元配列に格納 ・配列に格納した値で、データチェックなどを行う予定  テキストファイル内のデータは、下記内容となり要素数も固定ではなく変動する   A=1,2,3・・・   B=11,22,33・・・ 実際のソースは、 //配列 ArrayList list = new ArrayList(); //配列格納 1レコード毎用 ArrayList listtmp = new ArrayList(); while ((strGenderTextLine = objReader.ReadLine()) != null) {  string strBuffer;  //「=」前の値格納用変数  string[] strBuffer2; //「=」後の値格納用配列  listtmp=null;  //strtmpに「=」前の値を格納  strtmp = TextLine.Split('=').GetValue(0).ToString();  //strtmp2に「=」後の値を格納(配列)  strtmp2 = TextLine.Split('=').GetValue(1).ToString().Split(',');  for (int i = 0; i <= strtmp2.Length - 1; i ++)  {   //[i,0]に、「=」前の値を代入   if (i == 0)   {   listtmp.Add(strtmp);   }   else   {   listtmp.Add(strtmp2[i].ToString());   }  }  //list配列にlistTmp配列を格納(配列の配列)  list.Add(listtmp);  intT = intT + strtmp2.Length;  //行数カウント  intTLine = intTLine + 1;  } ここから、配列「list」内に入っている値を閲覧することができる方法を教えていただければと思います。 宜しくお願いいたします。

  • 動的配列の賢い使い方

    動的配列について質問です。 構造体を動的配列で今ボタンを押すたびに値を追加しています。 i = i+1 Redim preserve a(i) as ユーザ定義 ただこの方法だと追加するだけならよいのですが、 削除の時に問題があります。 例えば、配列が5つあるとします。 削除のボタンをクリックし2番目の配列を削除したとします。次に追加ボタンをクリックすると6番目に追加します。 これですと、2番目の値がないのに(5つしかないのに)6つ分のメモリを確保することになると思います。 上手はメモリ確保方法はないでしょうか? 構造体のデータは、 ・index ・文字列 ・数値 をそれぞれ持っており、indexは一応追加するごとに増えていくようになっています。 うまく説明できませんが、よろしくお願い致します。

  • 配列のSession格納、及び取得方法について

    お世話になります。 現在Visual Studio 2005でプログラム作成中です。 質問内容は、 配列(文字列を格納)をSessionに渡し、次ページでその配列の値を取得できるかという点です。 ***(a.aspx.vb)抜粋*** Dim a() As String Redim a(DataTable1.Rows.Count) For i As Integer 0 to DataTable1.Rows.Count - 1 a(i) = CType(DataTable1.Rows(i).Item(0)) Next Session("a.list") = a(DataTable1.Rows.Count) Session("a.count") = DataTable1.Rows.Count ***(b.aspx)抜粋*** Dim b() As String = CType(Session("a.list"), String) Dim bCount as integer = CType(Session("a.count"),Integer) Dim Name as String For i As Integer 0 To bCount Name = CType(b(i),String) Next としているのですが、取得できません。 配列に格納されたものをSessionに格納し、取得することは可能なのでしょうか。 また、その他に適切なものがあればご教授ください。 よろしくお願いいたします。

  • Visual Basicでデータベース接続について

    こんにちは。 VB初心者です。 前任者が作成したCSVファイルをメモリに格納するプログラムから Oracleテーブルのデータからメモリへ格納するプログラムへ 変更したいのですが、全くのVB初心者でわかりません。 ヒントでもいいですので教えてください。 CSVファイルをメモリに格納するプログラムは以下の通りです。 Function ReadCSV(ByVal szFilePath As String) As String()() ' (全般) に Imports 追記 ' Imports System.IO ' Imports System.Text Dim arrayTempLines()() As String = {} ' ストリームを開きます Dim reader As New IO.StreamReader(szFilePath, System.Text.Encoding.Default) Dim iIdx As Integer = 0 ' 一気に読み込みます Dim szData As String = reader.ReadToEnd() ' 不要な文字を取り除きます szData = szData.Replace(vbCr, "") ' 改行で分離して配列に格納します Dim arrayLines() = szData.Split(vbLf) Dim szLine As String For Each szLine In arrayLines Dim iCount As Integer = 0 Dim szTemp As String = "" Dim bValid As Boolean = False If szLine.Length > 1 Then ' 配列の追加します ReDim Preserve arrayTempLines(iIdx) ' カンマ区切りで分離して配列に格納します arrayTempLines(iIdx) = szLine.Split(",") ' データのチェックをします If arrayTempLines.Length >= 1 And _ arrayTempLines(iIdx)(0) <> "" Then bValid = True ' 不要データを除きます For Each szTemp In arrayTempLines(iIdx) arrayTempLines(iIdx)(iCount) = _ szTemp.Replace(Chr(34), "").TrimEnd() ' Chr(34)は"のことを指します iCount += 1 Next ' 配列数チェックをします If bValid Then iIdx += 1 End If Next ' 配列を切り詰めます 'ReDim Preserve arrayTempLines(iIdx - 1) ' 読み込み用のストリームを閉じます If (Not reader Is Nothing) Then reader.Close() reader = Nothing End If ReadCSV = arrayTempLines End Function 以上です。 ちなみに、Oracleテーブルの中にはフィールドが二つあります。