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

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

ただいまの
回答率

91.25%

  • VBA

    1177questions

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

VBA 動的にCollectionを生成

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 133

前提・実現したいこと

VBAで動的にCollectionを生成したいです。

発生している問題・エラーメッセージ

Type ブロック外では無効なステートメントです。

該当のソースコード

Sub Sample34()

    Dim people() As String
    people = Split("Tanaka", "Yamada")

    Dim Member() As String
    ReDim Member(UBound(people))

    Dim ii As Integer
    For ii = 0 To UBound(people)
        Member(people(ii))  As Collection
        Set Member(people(ii)) = New Collection
    Next

    Tanaka.Add 25, "age"
    Tanaka.Add 090, "number"

    Yamada.Add "test@test.com", "mail"
    Yamada.Add "tokyo", "addres"

    MsgBox Tanaka.Item("age")               
    MsgBox Yamada.Item("mail")   

End Sub

試したこと

田中と山田という人物に対して、年齢やメールアドレスを登録したいです。
登録項目は人物によって違います。(例)田中には年齢を登録するが、山田には登録しない
macを使っているのでDictionaryオブジェクトは使えません。
あとで人物全員に対して処理を行うことも考えられるので、
田中と山田をMemberというグループに所属させ、
あとでそのMemberに一括で処理ができるようにと考えております。

補足情報(言語/FW/ツール等のバージョンなど)

macOS High Sierra バージョン10.13.2
Excel バージョン 15.41

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

0

やりたかったことは以下のようなことですか?

Sub Sample35()

    Dim people() As String
    people = Split("Tanaka,Yamada", ",")

    Dim members As Collection
    Set members = New Collection

    Dim ii As Long
    For ii = LBound(people) To UBound(people)
        members.Add New Collection, people(ii)
    Next ii

    Dim Tanaka As Collection
    Set Tanaka = members.Item("Tanaka")
    Tanaka.Add 25, "age"
    Tanaka.Add 90, "number"

    Dim Yamada As Collection
    Set Yamada = members.Item("Yamada")
    Yamada.Add "test@test.com", "mail"
    Yamada.Add "tokyo", "addres"

    MsgBox Tanaka.Item("age")
    MsgBox Yamada.Item("mail")

End Sub

以下元のコードでミスしていると思われる箇所です。

 Split関数
Dim people() As String
people = Split("Tanaka", "Yamada")

この書き方だと(少なくともWindows版では)"Tanaka"しかpeople()の中に入りません。

両方入れる場合は

Dim people() As String
people = Split("Tanaka,Yamada", ",")

または

Dim people() As Variant
people = Array("Tanaka", "Yamada")

の書き方になると思います。

 Member()

Collectionを辞書的に使いたい、その辞書をMember()にまとめたい、と考えるとMember()の型はCollectionですよね?

Dim Member() As StringDim Member() As Collection

配列の添え字に文字列は使えないので

Set Member(people(ii)) = New Collection
↓
Set Member(ii) = New Collection

としか書けません。

Member(people(ii))  As Collection


の意図がいまいちわかりませんでしたが、もしかして型変換をしようとしているのでしょうか?

VBAでは値型のみCStrなどの関数で型変換できますが、それ以外は「その型の変数に入れる」ぐらいしか方法がありません。

なぜType ブロック外では無効なステートメントです。のエラーが発生したかをざっくり説明すると
ユーザー定義型のフィールド宣言の構文と同じ書き方をしたためです。

上記の行には予約後のAsが入っているため、変数宣言などの一種だと解釈されます。
しかし行頭にDimなどが存在しないため普通の変数宣言ではありません。
Asを使いつつ、行頭にDimなどが無いパターンはユーザー定義型のフィールド宣言時のみとなります。
しかし、書かれている場所はType~End Type(Typeブロック)で囲まれていないため、Type ブロック外では無効なステートメントです。のエラーが発生します。

'ユーザー定義型の定義
    'Personという名前でNameというString型のフィールドを持つ型
Type Person
    Name As String
End Type

17/12/26追記

Dim Tanaka As Collection
Set Tanaka = members.Item("Tanaka")
Dim Yamada As Collection
Set Yamada = members.Item("Yamada")
上記4行をfor文で動的にしたくて
For ii = LBound(people) To UBound(people)
members.Add New Collection, people(ii)
Dim people(ii) As Collection
Set people(ii) = members.Item(people(ii))
Next ii
としました。

結論から申し上げると「VBAでは不可能」です。

VBAではプロシージャの実行時に使用する変数を全て初期化するため、実行するまで名前の決まらない変数は作成できません。

出来たとしても、エディタの支援を全て投げ捨てることになるため、ただやりにくいだけになるかと思います。

雰囲気だけなら以下のような書き方もできますが、私個人としてはオススメしません。

With members
    'members!Tanaka と members("Tanaka") は同じ意味

    !Tanaka.Add 25, "age"
    !Tanaka.Add 90, "number"

    !Yamada.Add "test@test.com", "mail"
    !Yamada.Add "tokyo", "addres"

    MsgBox !Tanaka.Item("age")
    MsgBox !Yamada.Item("mail")

End With

 おまけ:エラーの原因

Dim people(ii) As Collectionは純粋にpeopleという名前の変数の宣言だと解釈されます。
さらに(ii)となっているため、静的な配列(要素数が固定の配列)変数の宣言と解釈されます。
しかしiiは変数のため、定数ではありません(固定されていません)。
結果として、「静的配列の変数宣言に定数を使っていない」と解釈され、「定数式が必要です。」のコンパイルエラーが発生します。
実際は変数宣言も重複しているため、「定数式が必要です。」を解消しても「同じ適用範囲内で宣言が重複しています。」のコンパイルエラーが発生します。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/25 08:10

    ご回答有り難うございます。
    今は時間が取れないので、のちほどコメントいたします。
    申し訳ありません。

    キャンセル

  • 2017/12/26 09:00

    遅くなり申し訳ございません。取り急ぎ気になった点をひとつ。

    Dim people() As Variant
    people = Array("Tanaka", "Yamada")
    上記2行に変更いたしました。

    Dim Tanaka As Collection
    Set Tanaka = members.Item("Tanaka")
    Dim Yamada As Collection
    Set Yamada = members.Item("Yamada")
    上記4行をfor文で動的にしたくて
    For ii = LBound(people) To UBound(people)
    members.Add New Collection, people(ii)
    Dim people(ii) As Collection
    Set people(ii) = members.Item(people(ii))
    Next ii
    としました。

    しかし「定数式が必要です。」というエラーになりました。
    原因はこちらでも時間の許す時に調べます。
    取り急ぎ現状の報告でした。

    キャンセル

  • 2018/01/10 14:28

    ご返信が遅くなり誠に申し訳ございません。
    「VBAでは不可能」とのこと、承知いたしました。
    エラー原因の説明も丁寧にしてくださり、感謝いたします。
    ありがとうございました。

    キャンセル

0

「Member(people(ii))  As Collection」の前に「ReDim」を付けて下さい。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/22 11:43

    ご回答有り難うございます。
    「配列要素のデータ型を変更することはできません。」というエラーになりました。

    キャンセル

  • 2017/12/22 12:04

    よくみると最初の宣言が「Dim Member() As String」になってますね。「String → Collection」

    キャンセル

  • 2017/12/22 12:28

    アドバイスありがとうございます。
    「String → Collection」した後に「ReDim」も追記しましたが、
    「ReDim Member(people(ii)) As Collection」の行が
    「型が一致しません」というエラーになります。

    キャンセル

0

【Mac】MacのExcelVBAでもDictionaryオブジェクトが使えた!というか自作(コピペ)できた! という情報があります。

MacでもVBAでDictionary相当のオブジェクトが使えるらしいです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/22 11:58

    ご回答有り難うございます。
    Office 2011用と書かれていますが、私が使っているエクセルは最新版になります。
    この情報は知っていましたが、
    バージョン違いによる不具合が起きないか心配だったので使っていません。

    キャンセル

0

シートにデータ(メンバー列、氏名、年齢、etc)を作って、
メンバー列の値をコレクションに入れて、
コレクション毎に処理する方法が、
簡単で分かりやすく、データの調整もしやすいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/10 14:29

    ご回答有り難うございます。
    検討してみます。

    キャンセル

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

ただいまの回答率

91.25%

関連した質問

  • 解決済

    2行以上連続で追加行を増やしたい

    実現したいこと 【要望】 データ管理をしているエクセルです。 社員データを追加したい場合、一番下の行に追加するのではなく、間に行を追加して入力していきたいのです。1行ずつ追加す

  • 受付中

    VBAを用いてバッチファイルを作成するツール

    前提・実現したいこと 業務でVBAを用いてバッチファイルを作成するツールが必要となりました。 ActiveDirectoryのUID棚卸しの為に使用します。 添付画像のような

  • 解決済

    VBA 2次元動的配列で、行数を順次増やす方法について

    前提・実現したいこと 現在、2次元の動的配列において、順次行数、列数を増やすマクロを作成しようとしています。 発生している問題・コード 具体的には、Arrで定義した2次元

  • 解決済

    VBAの配列の質問

    VBAの配列で教えてほしい事があります。 同一ブック内に2つのsheetがあります。 ”集計結果”と”一時保管”です。 ”一時保管”はA~D列にデータが入っています。

  • 解決済

    【VBA】特定の文字までを取得する方法

    VBAのことでお聞きしたいことがあります。 ■やりたいこと ・サイトのディレクトリデータが入っている列から最後の「/」以降の文字を除いた文字を取得 例)「/test/tes

  • 受付中

    【VBA】サブディレクトリも含めたファイル一覧を素早く取得したい

    以下のSample1とSample2はどちらもC:\Tempのサブディレクトも含めたファイル一覧を取得する関数です。 Sample1は'Sample2'よりも実行時間が短いですが、

  • 解決済

    テキストボックスを使用した問題を作成(エクセル)

    【前提】 エクセル・ユーザーフォーム上にテキストボックスを3つ・コマンドボタンを一つ配置しています。 【実現したいこと】 問題の答えをテキストボックスに入力・コマンドボタンをクリッ

  • 解決済

    VBA高速化について

    20個のエクセルファイルを読み込み、特定のシートにあるテーブルから特定の値を探し出し、その右横にあるセルの値を取り出します。 集計用のエクセルのテーブルでも、同じ特定の値をテーブル

同じタグがついた質問を見る

  • VBA

    1177questions

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