
VBAにチャレンジし始めて、1ヶ月ほどの者です。
WorksheetFunctionの引数にVBAの配列を入れて計算させたいと思っています。
例えば、作業用の配列temp_arrayを定義し、temp_array()に格納した数字の平均値をWorksheetFunctionで求めるといったことです。
しかし、
Dim temp_array() As Variant
Dim a As Double
a = WorksheetFunction.Average(temp_array())
としても、
「実行時エラー'1004'
WorksheetFunctionクラスのAverageプロパティーを取得できません」
というエラーで叱られます。
ネットで調べていると、Excelのワークシート関数には、引数として配列を扱えるものが多いとあったので、試してみています。
例えば、参考にしたのは下記のサイトの記述です。
http://www.clayhouse.jp/array/array03_d.htm
もちろん、平均値を求めるぐらいなら、自分で関数をつくった方が早いのだとは思いますが、エクセルには色々な統計関数があるので、本当に配列として、WorksheetFunctionに簡単にわたせるなら、相当プログラムが楽でシンプルにできるなぁと思います。
もし、よくご存じの方がいたらアドバイスいただけませんでしょうか?
No.2ベストアンサー
- 回答日時:
temp_array()の中は何がはいっているのでしょう?
その中身の問題じゃないですか?
文字列だったらエラーになります。
Dim temp_array() As Variant
Dim a As Double
temp_array() = Array(1, 2)
a = WorksheetFunction.Average(temp_array())
MsgBox a
この回答への補足
すいません。
実は、大きな配列から、特定の範囲の平均値を求めるために、
まず、大きな配列から対象範囲を切り出して、temp_array()に格納するという部分を関数としてつくってありました。
関数の戻り値が配列で、その配列をtemp_array()に代入しているのですが、代入結果の各要素をMsgBoxで表示させると、確かに対象となる部分の数字が5つ表示されるので、データの中身には疑問を持っていませんでした。
でも、全く同じ5つの数字をArrayで指定し直して、WorksheetFunction.Averageに渡すとちゃんと計算されました。
やはり、temp_array()のデータの中身に問題があるようです。
相変わらず何が問題なのかは皆目検討がつきませんが、その点は、投稿した質問内容とは異なる部分の問題のようです。
ありがとうございました。
早速のアドバイスありがとうございます。
アドバイスのコードを試したらちゃんとできますね。
今は試しなので、中には4桁の整数を5つ入れてます。
配列内にちゃんと数字が入っていることは確認しているのですが。
サッパリわからなくなってきました。
もう少し原因究明してみます。
No.8
- 回答日時:
こんにちは。
余計なことを書くようで、もしお気に障ったら、すみませんです。
どうやら、私の書いたメッセージはどうも伝わらなかったようで、とても残念です。
VBAにかなり自信のある方だとお見受けしましたが、端的に言うと、掲示板では、VBAの質問でVBAのコードを見なければ、お話は進まないということです。できれば、回答者側に回ってみてください。見えないものが見えてきます。
CSVであろうが、どうであろうが、配列の中身に文字列になるというのは、そこのコードのどこかにミスか不足があるのだと考えたのです。繰り返しますが、エラーは、そのプロセスに問題があるのであって、文字列であるから、というのは、結果論なのです。
それと、配列の中身を調べるなら、ブレークポイントを入れて、ローカルウィンドウで、変数を確認すれば済みます。
Variant型配列だけで、そのデータが文字列になるなんていうことは、ありえないのです。文字列を文字列として入れたからなのです。
あまり、参考にはならないと思いますが、最初に、今回のような内容を出されていたら、こんなコードを出していたと思います。なお、最近は、変数は重複して使うようですが、Step モード(F8)で見やすいように、以下は、ほとんど重複して使ってはいません。
シートにデータが出力されるものです。
'---------------------------------------------
Sub CSVImport()
Dim FileName As String
Dim FNo As Integer
Dim buf As String
Dim myAr() As Variant
Dim myArBuf As Variant
Dim myArVal() As Variant
Dim i As Long
Dim j As Integer
Dim k As Long
Dim v As Variant
Dim ret1 As Double
Dim ret2 As Double
Const sSEP As String = "," '区切り文字
Const STARTL As Long = 5 '切り出し数(始め)
Const ENDL As Long = 20 ' '' (終わり)
FileName = Application.GetOpenFilename("CSV ファイル(*.csv),*.csv")
If FileName = "False" Then
Exit Sub
End If
'
FNo = FreeFile()
Open FileName For Input As #FNo
Do Until EOF(FNo)
Line Input #FNo, buf
myArBuf = Split(buf, sSEP)
ReDim Preserve myAr(i + UBound(myArBuf))
For Each v In myArBuf
myAr(i) = v
i = i + 1
Next v
Loop
Close #FNo
ReDim myArVal(ENDL - STARTL)
For Each v In myAr()
If STARTL <= j And ENDL >= j Then
myArVal(k) = Val(v) '文字列がなければ、CLng などの方がよい
k = k + 1
End If
j = j + 1
Next
'シートへの出力
Cells(1, 1).Resize(UBound(myArVal) + 1).Value = Application.Transpose(myArVal())
Cells(UBound(myArVal) + 2, 1).Formula = "=AVERAGE(R1C1:R[-1]C)"
Cells(UBound(myArVal) + 3, 1).Formula = "=STDEVP(R1C1:R[-2]C)"
'ユーザー定義関数との比較
ret1 = myAverage(myArVal())
ret2 = mySTDEV(myArVal())
Cells(UBound(myArVal) + 2, 2).Formula = ret1
Cells(UBound(myArVal) + 3, 2).Formula = ret2
End Sub
''
Private Function myAverage(myAr() As Variant)
'平均値
Dim mSum As Double
Dim i As Long
Dim v As Variant
For Each v In myAr()
mSum = mSum + v
i = i + 1
Next v
myAverage = mSum / i
End Function
'
Private Function mySTDEV(myAr() As Variant)
'標準偏差
Dim ave As Double
Dim mSum As Double
Dim i As Long
Dim dev As Double
Dim v As Variant
For Each v In myAr()
mSum = mSum + v
i = i + 1
Next v
ave = mSum / i '平均値
'
For Each v In myAr()
dev = dev + (ave - v) ^ 2
Next v
mySTDEV = (dev / i) ^ (1 / 2)
End Function
'------------------------------------
No.7
- 回答日時:
こんばんは。
>原因究明ができましたので、問題が解決いたしました。
うーん。読まされている側は、狐につままれたような感じで、逆に、何が何だか分からないのですが。別に、配列変数が、Variant 型だから、いけないというわけでもないのです。実際の内容が分からないので、一体、原因はなんだったのか、さっぱり分かりません???自己解決してしまったから、もう答える義務もゆかりもないのかもしれませんが、何か、すっきりとしていないものが残ります。
自称専門家さん以外の、ここで回答している人たちの半分以上は、「教える」というステータスを誇示しているのではなくて、ここで、同じように学習しているわけで、やっぱり原因を知りたいと思うのです。つまり、教えることと、教わることのインタラクティブということです。
私は、#6で、
>>やはり、temp_array()のデータの中身に問題があるようです。
>いいえ、その前の問題です。その切り出し方法が問題ですね。肝心なところが書かれていません。
と書いたのですが、配列の中身は、結果論です。
単に、文字列の数字を数値に置き換えるなら、あえて、Average 関数など使う必要などないわけです。ワークシートの数字自体は、ほとんどは、Variant 型で、そこには、文字列と数値の区分けなど存在していません。文字列として扱ったときに初めて文字列となるわけです。
それに、別で書かれた、Watch式っていうのは、そこで、True/False で、コードをストップさせて値を見るものであって、通常は、ローカルウィンドウとステップイン(F8)だけで十分だと思います。
これに対して、答えなくてはならない義務とかはないけれども、読んでいる側は、終わっていないということだけは伝えておきますね。
アドバイス頂いたのに、当方の言葉足らずで、すいません。
私がつくっていたのは、数万点のデータが入ったcsvファイルを一旦、原配列()に読み込んだ上で、特定の範囲の部分だけの平均値や標準偏差を求めようというものです。
そこで、特定の範囲のデータ列だけ、作業用配列()として切り出す関数をつくりました。
関数の引数は始点,終点,原配列()の3つで、戻り値は作業用配列()です。
配列の受け渡しの際のデータ型のことは細かく考えたくなかったので、
原配列も作業用配列もバリアント型にすれば、すくなくとも関数との配列の受け渡しでトラブルはないだろうと思ったのが失敗です。
一昨日までデバッグツールの使い方も知りませんでしたので、関数からの戻り値である配列の各要素をMsgBoxで表示させたり、エクセルのセルに書き込んだりて中身を確認していたのですが、表示されるのは、想定通りの数字だったので、頭を抱えたわけです。
しかし、ウォッチ式で関数から戻ってくる配列の中身を確認したら、全て数字が文字列として入っていたことがわかりました。
csvファイルから読み込んだ数字が原配列に全て文字列として入ってしまっていたのが、トラブルの原因でした。
>ワークシートの数字自体は、ほとんどは、Variant 型で、そこには、文字列と数値の区分けなど存在していません。
私は、データ型に関する理解が不十分なのですが、WorksheetFunction.Average()は渡した配列の中身が文字型だとダメみたいです。
結果的に、原配列も作業用配列もDoubleとして宣言したら、エラーもなくうまくいった次第です。
No.6
- 回答日時:
こんにちは。
>やはり、temp_array()のデータの中身に問題があるようです。
いいえ、その前の問題です。その切り出し方法が問題ですね。肝心なところが書かれていません。
'----------------------------------------
Dim Ar As Variant
Const MYTXT As String = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16"
Ar = Split(MYTXT, ",")
MsgBox WorksheetFunction.Average(Ar)
'----------------------------------------
これでエラーが出ます。
なお、VBEditor の F8 を押せば、ステップモードになりますから、そこで、ローカルウィンドウを見て、中を確認すればよいです。しかし、もう、以下のようなコードにしたら、ワークシート関数はあまり意味を持ちません。
'----------------------------------------
Sub Test2()
Dim Ar As Variant
Dim Ar2() As Double
Dim i As Long
Const MYTXT As String = "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16"
Ar = Split(MYTXT, ",")
ReDim Ar2(UBound(Ar))
For Each v In Ar
Ar2(i) = v
i = i + 1
Next
MsgBox WorksheetFunction.Average(Ar2)
End Sub
'----------------------------------------
#5さんともども、ありがとうございます。
原因究明ができましたので、問題が解決いたしました。
自作関数とWorksheetFunctionを組み合わせることで、
とても、スッキリと短いコードで思い通りの結果が得られるようになりました。
デバッグツールの使い方も覚えることができましたし、
皆様のご助言に感謝、感謝です。
No.5
- 回答日時:
こんにちは。
#2さんのご指摘で分かっているかもしれませんが、配列変数の数値の中に、ワークシートのエラー値が含まれていれば、そのような実行時エラーが発生します。ワークシート関数には、そのようなエラー値を無視する機能がありません。
それから、VBAでは、ワークシート関数を使うのは、関数の仕組みをある程度理解していないと、難しいことが多いと思います。算術型の関数の多くの引数は、文字列と数値だけしか区分けしませんので、それ以外は、エラーを出すことが多いです。
ありがとうございます。
原因は、配列をVariantと宣言していたためか、
配列に数字が文字列として代入されていたためということがわかりました。
デバッグツールの使い方をよくわかっておらず、
配列の中身をMsgBoxで表示させるという原始的な方法で確認していたので、
文字列なのか、数字なのか、区別できていませんでした。
No.4
- 回答日時:
例データ 元データ A1:C9 D列横計
1236
57719
12141238
63 ーー>和
ーーー
純粋に配列とはいえないかもしてないが、ヴァリアント変数で
コード
Sub test01()
Dim tmp As Variant
tmp = Range("a1:C3")
MsgBox "平均= " & sumary(tmp)
End Sub
Function sumary(tmp)
For Each x In tmp
MsgBox x
t = t + x
n = n + 1
Next
MsgBox t
sumary = t / n
End Function
====
Sub test02()
Dim tmp As Variant
tmp = Range("a1:C3")
MsgBox "平均= " & avgary2(tmp)
End Sub
Function avgary2(tmp)
avgary2 = WorksheetFunction.Average(tmp)
End Function
ありがとうございます。
どうやら、配列データに理解不能な現象が起きているのが原因のようです。
プログラミングというのは、一旦、行き詰まると出口が見えなくなる迷路のようです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) Sheet1のA列にコードB列にメアド、Sheet2のB列にコード一覧とD列にメアド一覧があり、Sh 3 2022/10/19 11:57
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- Visual Basic(VBA) Excel のユーザー定義関数でソルバーが動作しない 1 2022/09/05 19:51
- Visual Basic(VBA) VBAでのMATCH関数 3 2022/10/17 19:06
- Visual Basic(VBA) 型が一致しませんとエラー 6 2023/07/06 20:14
- Visual Basic(VBA) vba 等間隔の列に対しての計算 6 2022/05/17 20:15
- Visual Basic(VBA) vbaのvlookup関数エラー原因を教えていただけないでしょうか。 3 2022/04/25 16:16
- Visual Basic(VBA) エクセルのマクロについて教えてください。 2 2023/03/08 09:08
このQ&Aを見た人はこんなQ&Aも見ています
-
エクセルVBA 配列からセルに「関数式」を一気代入したい
Visual Basic(VBA)
-
worksheetFunctionクラスのVlookupプロパティを取得できません エラーへの対応
Visual Basic(VBA)
-
VBA 配列に格納した値の平均のやり方についてお教え願います
Visual Basic(VBA)
-
-
4
VBAで配列の計算
Excel(エクセル)
-
5
VBAでワークシートを引数としてサンプル関数に渡したい
Visual Basic(VBA)
-
6
VBAで保存しないで閉じると空のBookが残る
Excel(エクセル)
-
7
【Excel VBA】マクロでExcel自体を終了させたい
Excel(エクセル)
-
8
エクセル:マクロ「Application.CutCopyMode = False」って?
Excel(エクセル)
-
9
EXCEL VBA セルに既に入力されている文字に文字を追加する
Excel(エクセル)
-
10
countif/sumifのようなVBA関数
Visual Basic(VBA)
-
11
特定のPCだけ動作しないVBAマクロがあります。その理由は?
Visual Basic(VBA)
-
12
array関数で格納した配列の型を変更する
Visual Basic(VBA)
-
13
VBAでの Replace関数で、ワイルドカードは使えないのでしょうか?
Visual Basic(VBA)
-
14
日付型のフィールドに空白を入れる方法を教えてください
その他(データベース)
-
15
エクセルのエラーメッセージ「400」って?
Visual Basic(VBA)
-
16
VBA:日付を配列に入れ別セルに転記するとデータ型が変わる
Visual Basic(VBA)
-
17
VBAのコマンドボタンの文字列の改行方法は?
Visual Basic(VBA)
-
18
ユーザーフォームをホイールでスクロールする方法(Excel2000VBA)
Excel(エクセル)
-
19
エクセルVBAで5行目からオートフィルタモードに設定したいたい
Excel(エクセル)
-
20
エクセルのラベルの値(文字列)を垂直方向で中央揃えにするには?
Excel(エクセル)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Ruby初心者です。
-
VBAのWorksheetFunctionの引数...
-
丸いアイコンを丸く並る方法
-
MATLABで配列をファイルへ書き...
-
COLUMN(1:1)の意味を教え...
-
ruby on railsのscaffoldで配列...
-
配列の値を置換するにはどうす...
-
rubyによる2次元配列形式のデー...
-
エクセルへのデータの貼付時に...
-
Win32APIでシリアル通信をする...
-
VB 配列の内容をファイルに書...
-
C言語 exitの使い方
-
<a href=…>がうまくいかない
-
VisualStudio2022でC言語プログ...
-
条件演算子 ? :
-
Excel-vba 文字列と変数を...
-
Windows Media Playerで動画を...
-
シェルスクリプトでPHPのchr()
-
Windows11のカメラで動画を撮り...
-
数字の位ごとの値を表示するプ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
excelの、ある数式内の{}の意...
-
配列の値を置換するにはどうす...
-
vbsでテキストファイル内の文字...
-
VBAのWorksheetFunctionの引数...
-
エクセル、この関数の意味は?
-
COLUMN(1:1)の意味を教え...
-
数値を浮動小数点32bitHEXコー...
-
エクセルへのデータの貼付時に...
-
○桁にある数値を取得する VB.N...
-
VB6で配列を文字列に変換する方...
-
VBAで配列に文字列が入らない?
-
RichTextBoxの改行を認知してく...
-
copyRecordsetの数値16桁以上に...
-
【エクセル】 関数による電子...
-
複数ディレクトリの監視(VB.NET...
-
VBSで特定の文字列が含まれる場...
-
VB.NET 2つの配列を連動して並...
-
Javaのプログラムをルビー言語に。
-
VB 配列の内容をファイルに書...
-
ruby on railsのscaffoldで配列...
おすすめ情報