• ベストアンサー

[Excel2000_VBA] 型が一致しませんメッセージが表示

各サイトを調べたのですが、自分のレベルに合った解答内容がなくよく理解できなかったので、質問させて頂きます(初歩的な質問で申し訳ありません) ユーザー定義を使用し、以下のコードを作ってみました。 配列を引数にして、まとめて返したいと考えていますが、構造体を使用すると「型が一致しません」と表示されてしまいます。 何が原因しているのでしょうか? さっぱり分かりませんので、ご教示お願いいたします。 Type test aaaa As Integer End Type Sub sbTest() Dim myAns() As test myAns = Sample1(myAns) End Sub Function Sample1(ByRef Ans() As test) Dim i As Integer Dim ret(0 To 9) As test For i = 0 To 9 ret(i).aaaa = i Next Ans = ret '配列名で配列を戻り値 End Function

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

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

AsnをRef引数で渡すのであればSample1はSubでいいと思いますよ Functionにするなら戻り値を定義します ' 戻り値を定義 ... As test() Function Sample1() As test()   Dim i as Integer   Dim Ans(0 to 9) As test   for i = 0 to 9     Ans(i).aaa = i   next   Sample1 = Ans End Function ' 参照渡しの引数なら Subプロシージャで Sub Sample2(ByRef Ans() as Test)   Dim i as Integer   ' 引数の配列の 下限から上限までの添え字の取得を   ' LBound/UBoundで取得   for i = LBound(Ans) to UBound(Ans)     Ans(i).aaa = i   next End Sub

enotama
質問者

お礼

試してうまくできました。 ありがとうございます。 構造体と配列を扱うのが苦手で四苦八苦しており、型を宣言して返すという考えもありませんでした。

その他の回答 (1)

  • junbei
  • ベストアンサー率55% (5/9)
回答No.2

(言っている意味はNo.1さんと同じなのですが)もう少し噛み砕くと、 呼び出し方に問題があります。 まず、よく意味を考えてみましょう。 myAns = Sample1(myAns) だと、「myAns」に「Sample1(myAns)」を代入しろ。という命令になります。 ここで「Sample1(myAns)」とは何だろう?と考えると、Function Sample1 で何も返却していないので「何もない」もの(Variant型のNull)が返ってきます。 つまり、この書き方では「test型の動的配列」に「何もないもの」を代入しようとしているわけです。 このときに「型が一致しません」エラーが発生しています。 エラーを解消しようとするなら、以下のように書いてみてください。 Type test aaaa As Integer End Type Sub sbTest() Dim myAns() As test 'myAns = Sample1(myAns) '★補足:「左辺のmyAnsにSample1の戻り値を代入する」という意味。 '    つまり型が一致しない。 '    →この場合Sample1の戻り値はVariant型であるため '正しくは以下のどちらか '(1) myAns = Sample2() '★補足:「左辺のmyAnsにSample2の戻り値を代入する」という意味。 '    つまり型が一致する。 '    →この場合Sample2の戻り値はtest()型であるため '(2) Call Sample3(myAns) '★補足:「myAnsをByRef引数としてSample3を呼び出す」という意味。 '    ByRef引数は、呼出元でもファンクション内部の変更の影響を受ける '    →この場合、Sample3の内部でAnsに配列をセットしているので、呼出元のmyAnsも同じ状態となる End Sub Function Sample1(ByRef Ans() As test) 'もともとのサンプル=ファンクションの型が定義されていないので、暗黙でVariant型になる Dim i As Integer Dim ret(0 To 9) As test For i = 0 To 9 ret(i).aaaa = i Next Ans = ret End Function Function Sample2() As test() 'ファンクション戻り値として配列を返却 Dim i As Integer Dim ret(0 To 9) As test For i = 0 To 9 ret(i).aaaa = i Next Sample2 = ret '★ファンクションの戻り値に配列をセット End Function Sub Sample3(ByRef Ans() As test) 'ByRef引数として配列を返却 Dim i As Integer Dim ret(0 To 9) As test For i = 0 To 9 ret(i).aaaa = i Next Ans = ret '★ByRef引数の戻り値に配列をセット End Sub

enotama
質問者

お礼

詳しく説明下さり、ありがとうございます。 自分でも引数を更に引数と同じ変数に代入と?・・・迷いながらの作成でした。 > 'もともとのサンプル=ファンクションの型が定義されていないので、暗黙でVariant型になる このことを理解していませんでした。 きちんと型宣言してmyAns = Sample2()の方法で行うことにしました。

関連するQ&A

  • ある文字が含まれているセルの個数を結果表示

    いつもお世話になっております。 また詰まってしまいましたので質問させてください。 S列に「test」という文字が入っているセルの個数を集計し結果を セル「AC1」に表示したいのですがうまくいかずにおります。 なお、S列には様々な文字が入っているのでワイルドカードで検索しております。 データ数は変動します。 Sub Macro1() Dim c As Long Dim ans As Integer Dim i As Integer ans = 0 With ActiveSheet For i = Cells(65536, c).End(xlUp).Row To 1 Step -1 If Range("S" & i) = "*test*" Then ans = ans + 1 End If Next i Range("AC1") = ans End With End Sub 環境 Excel2003 以上、宜しくお願いします。

  • 型が一致しません

    下記はセルが0の時、行全体を表示しないにするようにするVBAですが、型が一致しませんとエラーになります、どこを直せばいいのですか。 Dim I As Integer Sub Macro4() For I = 4 To 76 If Cells(I, 8) = 0 Then Rows("I:I").Select Selection.EntireRow.Hidden = True End If Next I End Sub

  • VBA "double"から0.1を引くと・・・

    エクセルVBAですが、double型で変数を定義し、-80を代入します。 そこから0.1ずつを引いていきます。すると、途中から桁がおかしくなってしまいます。 (注:別に-80からでなくても、どの値からでも、また、引いていっても足していっても、遅かれ早かれ どこかから桁がおかしくなってしまいます。) -80 -80.1 -80.2 …中略 -80.8 -80.8999999999999 -80.9999999999999 … といった感じです。 どうしてこのようになってしまうのでしょうか。 また、このようにならないためにはどうしたらよいのでしょうか。 いかにサンプルプログラムを載せます。 ------------------------------------------ Sub test() Dim test As Double Dim i As Integer test = -80 For i = 1 To 100 test = test - 0.1 Cells(i, 1) = test Next i End Sub ----------------------------------

  • VBA「型が一致しません」とエラーが出ます

    下記記事の関連質問です。 Excel 文字列抜き出しについて https://okwave.jp/qa/q9979633.html 記事を参考に複数行にマッチするように下記のようにコードを考えましたが msplit(mRng, " ", iii)で「型が一致しません」とエラーが出ます。 なぜでしょうか? テスト用のA4セル 1 01 45124422 ミント 09/01~03/01 108 98 01/05~02/01 Option Explicit Sub test() Dim msplit As Variant Dim buf As String, i As Long, ii As Long, iii As Long, cnt As Long Dim mRng As Range For ii = 4 To Cells(Rows.Count, 1).End(xlUp).Row buf = Cells(ii, "A") For i = 1 To Len(Cells(ii, "A")) If Mid(buf, i, 1) = " " Then cnt = cnt + 1 Next For iii = 1 To cnt Set mRng = Cells(ii, "A") ’Stop Cells(iii + 1, ii) = msplit(mRng, " ", iii) Next Next Set mRng = Nothing End Sub Function msplit(ByRef mRng As Range, ByVal Spstr As String, ByVal num As Long) As Variant msplit = Split(mRng, Spstr)(num - 1) End Function

  • Excel2010 VBA 条件色付け

    Sub sample() Dim r As Range For Each r In Range("q6:q30") If myIsNumeric(r) Then r.Offset(0, 1).Value = "数字" Else r.Offset(0, 1).Value = "文字" End If Next End Sub Function myIsNumeric(Target As Range) Dim r As Range Dim buf, tmp Dim flg As Boolean Dim i As Integer buf = Target For i = 1 To Len(buf) tmp = Mid(buf, i, 1) If IsNumeric(tmp) Then flg = True Exit For End If Next myIsNumeric = flg End Function を数字が入ってたら塗りつぶさないで、 数字が入ってなかったら塗りつぶすように直したいです。 あああ→塗る あああ1-1→塗らない 住所→塗る 住所12→塗らない

  • VBA(Excel2003)で文字列の切り出し

    下のプロシージャーで全角半角混じりの文字列を切り出し、別の文字列で結合しようと思いますがうまくいく場合といかない場合があります。 イミディエイト・ウィンドウ上とCell上で動作が違います。 Cell上でうまく表示させるにはどうしたらいいでしょうか? Sub Test() Dim myString(2) As String Dim i As Integer myString(0) = "airueo" myString(1) = "かきくけこ" myString(2) = "さシすせそ" For i = 0 To 2 Debug.Print MidMbcs(myString(i), 1, 5) & "...テスト" Cells(i + 1, 1).Value = MidMbcs(myString(i), 1, 5) & "...テスト" Next i End Sub Function LenMbcs(ByVal str As String) LenMbcs = LenB(StrConv(str, vbFromUnicode)) End Function Function MidMbcs(ByVal str As String, start, length) MidMbcs = StrConv(MidB(StrConv(str, vbFromUnicode), start, length), vbUnicode) End Function

  • Excel VBA ByRef引数の型?

    Excel2010でセルに関数式を埋め込むマクロを書いています。 そこで、「ByRef引数の型が一致しません」というエラーが出て困っています。 プログラムの中からエラーの出る所だけを取り出してtest1,test2として試したところ、 test1はエラーが出て、test2はプログラムが動いて目的とするセルに関数式が挿入されました。 Sub test1() dim i, myR as integer myR = 30 For i = 7 To 31 Cells(4, i) = "=IF(" & ConvertToLetter(i) & i - 4 & "="""","""",SUM(" & ConvertToLetter(i) & "5:" & ConvertToLetter(i) & myR & ")/(" & myR & "-COUNTIF(" & ConvertToLetter(i) & "5:" & ConvertToLetter(i) & myR & ","""")))" next i End Sub test1でConvertToLetter(i)のiが青色で選択され「ByRef引数の型不一致」エラーとなってしまいます。 そこで、試しに一度変数iの値をkに渡して同じプログラムをtest2として実行してみました。 Sub test2() dim i, k, myR as integer myR = 30 For i = 7 To 31 k=i Cells(4, i) = "=IF(" & ConvertToLetter(k) & i - 4 & "="""","""",SUM(" & ConvertToLetter(k) & "5:" & ConvertToLetter(k) & myR & ")/(" & myR & "-COUNTIF(" & ConvertToLetter(k) & "5:" & ConvertToLetter(k) & myR & ","""")))" next i End Sub このtest2は、きちんと実行され、目的とするG4(~AE4)のセルに =IF(G3="","",SUM(G5:G30)/(30-COUNTIF(G5:G30,""))) という式が挿入されました。 質問1:なぜ、test1がダメで、test2ならうまくいくのかという理由がわかりません。 質問2:うまくいったtest2と同じ式を、もっと長いプログラムの中に入れるとやはり「ByRef引数の型が一致しません」エラーが出てプログラムが止まってしまいます。test2単独のプログラムならうまく動くのに、他のプログラムの一部に埋め込むとエラーが出る理由もわかりません。 VBAプログラムを試行錯誤しながら勉強している初心者です。どなたかご教示お願いします。 ちなみに、ConvertToLetterは、 Function ConvertToLetter(iCol As Integer) As String Dim iAlpha As Integer Dim iRemainder As Integer iAlpha = Int((iCol - 1) / 26) iRemainder = iCol - (iAlpha * 26) If iAlpha > 0 Then ConvertToLetter = Chr(iAlpha + 64) End If If iRemainder > 0 Then ConvertToLetter = ConvertToLetter & Chr(iRemainder + 64) End If End Function という、関数で定義しています。

  • カウンターボード⇒EXCEL2000にVBAでデ…

    カウンターボード⇒EXCEL2000にVBAでデータを取込みたい ロータリーエンコーダ(2相式パルス)のカウンターの値をカウンターボードを経由しEXCEL2000に取込みたいと考えています。 カウンターボードに付属してきたサンプルプログラムでは正常に動作します。(ボードは正常) そこでEXCELサンプルプログラムを動作したのですが、コンパイラーエラーが発生し動作しません。 ボード認識や初期設定は同じにしてあるため、EXCEL VBAのサンプルプログラムのミスだと思われます。 プログラムは下記に添付します。このうち"Acx Timer1.TimEnabled"変数が未定義というエラーが出ます。 また自分で変数を定義してみましたが、今度は”修飾子が不正”というエラーが出ます。 どう修正すれば動作する様になるでしょうか?ご教授ください。 '-------------------------------------------------------------------------------- ' Count '-------------------------------------------------------------------------------- Option Explicit Const EXP_SAMPLE = "カウンタ入力用サンプルです。" Const EXP_TITLE = "Countサンプル" Const PROG_TITLE = "カウンタ入力:" Dim ret As Integer '戻り値格納用 Dim i As Integer '一時的なカウンタ '-------------------------------------------------------------------------------- 'カウント一致検出 Private Sub AcxCnt1_OnDetectedMatch(ByVal ChannelNumber As Integer, ByVal MatchValue As Long, ByVal Direction As Integer) Range("lblDisp").Value = "カウント一致 CH" & ChannelNumber & " カウント値 = " & MatchValue & " 方向 = " & Direction End Sub 'エラー発生 Private Sub AcxCnt1_OnErr(ByVal Status As Integer) Range("lblDisp").Value = AcxCnt1.GetErrorString(Status) End Sub '-------------------------------------------------------------------------------- 'タイマイベント:カウント値表示処理 Private Sub AcxTimer1_Timer(ByVal TimerCnt As Long) Dim i As Integer Dim tmpStr As String 'カウント値の表示 tmpStr = "" For i = 0 To AcxCnt1.MaxChannelNumber - 1 tmpStr = tmpStr & "CH" & i & " = " & AcxCnt1.CountValue(i) & Chr(10) Next i Range("lblCount").Value = tmpStr End Sub 'カウント値のラッチ Private Sub chkLatch_Click() 'チェック If chkLatch.Value = True Then AcxCnt1.LatchCount = True 'ラッチ cmdApply.Enabled = True Else AcxCnt1.LatchCount = False 'ラッチ解除(通常読み込み) cmdApply.Enabled = False End If End Sub 'データ更新 Private Sub cmdApply_Click() AcxCnt1.LatchCount = True End Sub '表示クリア Private Sub cmdClear_Click() Range("lblCount").Value = "" Range("lblDisp").Value = "" End Sub '-------------------------------------------------------------------------------- 'カウント開始 Private Sub cmdStart_Click() Dim i As Integer For i = 0 To AcxCnt1.MaxChannelNumber - 1 AcxCnt1.CountEnabled(i) = True Next i AcxTimer1.TimEnabled = True End Sub '-------------------------------------------------------------------------------- 'カウント停止 Private Sub cmdStop_Click() Dim i As Integer AcxTimer1.TimEnabled = False For i = 0 To AcxCnt1.MaxChannelNumber - 1 AcxCnt1.CountEnabled(i) = False Next i End Sub '-------------------------------------------------------------------------------- 'ロード時の処理 Public Sub Load() '設定ファイルの読み込み AcxCnt1.ErrorMessage = False ret = AcxCnt1.LoadProperty(ThisWorkbook.Path & "\ACXCNT.INI") Sheet1.Name = "AcxCnt Count サンプル" Range("lblDisp").Value = "ボード名 : " & Chr(10) & _ "I/Oアドレス : " & " 0h" & Chr(10) & _ "割込み : " & "0" & Chr(10) & _ "チャネル数:" & "0" '自動検出 If ret <> 0 Then '設定ファイルがなければ検出/登録を試みる ret = AcxCnt1.AutoDetect("CNT000") If (ret = 0) Then AcxCnt1.DeviceName = "CNT000" 'デバイス名CNT000のボードを選択 If (fncOpen = 0) Then '初期化ルーチン実行 MsgBox EXP_SAMPLE, vbOKOnly + vbInformation, EXP_TITLE 'サンプル説明表示 End If Else MsgBox "ボードを自動的に検出できませんでした。" & vbCrLf & _ "[プロパティ]ボタンを押してボードを登録してください。" End If Else fncOpen '設定ファイルがあるのでそのまま初期化ルーチン実行 End If End Sub '-------------------------------------------------------------------------------- '初期化処理 Function fncOpen() As Integer AcxCnt1.TimEnabled = False ret = AcxCnt1.Open '初期化 If ret = 0 Then fncDispProperty 'プロパティの設定を表示 Else MsgBox "エラーコード = " & ret & vbCrLf & _ AcxCnt1.GetErrorString(ret), vbOKOnly + vbCritical, "初期化(Openメソッド)エラー" End If fncOpen = ret End Function '-------------------------------------------------------------------------------- 'プロパティページの表示 Private Sub cmdShowProperty_Click() Dim tmpBoardName As String, tmpDeviceName As String tmpBoardName = AcxCnt1.BoardName 'ボードが変更されたかどうかを知るために記憶します tmpDeviceName = AcxCnt1.DeviceName 'デバイス名が変更されたかどうかを知るために記憶します AcxCnt1.ShowProperty 'プロパティページを表示 'プロパティページでボードが変更された? If (tmpBoardName <> AcxCnt1.BoardName) Or (tmpDeviceName <> AcxCnt1.DeviceName) Then MsgBox "ボードが変更されました。" & Chr(10) & _ "初期化しなおします。" fncOpen '初期化時の処理(fncOpen内でタイマを開始) Else fncDispProperty '設定表示を更新 End If End Sub '-------------------------------------------------------------------------------- 'プロパティの設定状態を表示 Sub fncDispProperty() Range("lblDisp").Value = "ボード名 : " & AcxCnt1.BoardName & Chr(10) & _ "I/Oアドレス : " & Hex(AcxCnt1.IoAddress) & " h" & Chr(10) & _ "割込み : " & AcxCnt1.IrqLevel & Chr(10) & _ "チャネル数:" & AcxCnt1.MaxChannelNumber End Sub

  • VB6.0の参照渡し

    VC++6.0で作成したDLLへVBの配列を渡そうと思っています。 いくつかためしたのですが、 「配列引数は ByRef でなければなりません。」 というエラーがでてしまいます。 標準モジュール内の記述 Declare Function fncTest Lib "Test.dll" (ByRef test() As Long) As Long フォーム内 Private Sub Test_Click() dim test() as Long dim i as integer for i = 0 to 3 test(i) = i next i fncTest(Test()) End Sub とりあえず、こんな形でかいてみましたが、 Sub内のtest()の宣言方法、使用法等ご指導お願いします。

  • 配列の参照渡しで型が一致しません。

    エクセル2003です。 いつもお世話になります。 以下のコードを実行すると「配列の型が一致しません。」というエラーが出ます。 typeNameで確認しても配列の型はvariant()で正しいと思うのですが。。。 皆様のお知恵を拝借させていただけないでしょうか。 -------------------------------------- Sub main() Dim e As Variant e = fuN() Call pRo(e)  '←ここでエラーになる。 End Sub Function fuN() As Variant Dim a(0) As Variant a(0) = "zero" fuN = a End Function Sub pRo(ByRef c() As Variant) '処理っす End Sub --------------------------------------

専門家に質問してみよう