2

セルに次の数式があります。

=GetData("Channel_01","Chicago")

次のコードを実行します。

Public Function GetData(ChannelCode As String, Key As String) As String
    Dim sql As String
    Dim cmd As New ADODB.Command
    Dim outputTo As Range
    Set outputTo = Application.Caller    
    sql = "select * from ChannelData WHERE ChannelCode = ? AND Key1 = ?"
    Set cmd = getCommand(sql, ChannelCode, Key)
    Dim rs As ADODB.Recordset
    Set rs = cmd.Execute
    WritePivotRecordset ChannelCode, rs, outputTo.Offset(1, 0)
End Function

Public Sub WritePivotRecordset(ChannelCode As String, rs As ADODB.Recordset, destination As Range)
    Dim i As Integer
    '*** WHEN THIS LINE OF CODE IS REACHED AND EXECUTES, PROCESSING STOPS
    Set destination.Value = ChannelCode
    For i = 1 To rs.Fields.Count - 1    'skip first field
        destination.Offset(0, i).Value = rs.Fields(i).Name
    Next
    destination.Offset(1, 0).CopyFromRecordset rs
End Sub

問題は次の行で発生します。

'*** WHEN THIS LINE OF CODE IS REACHED AND EXECUTES, PROCESSING STOPS
    Set destination.Value = ChannelCode

これを設定すると、実行中の VBA スレッドなどを終了するスプレッドシートの再計算が呼び出されますか? 私はそう思ったので、出力を書く前にこれを試しました:

Application.Calculation = xlCalculationManual

しかし、同じコード行で、 アプリケーション定義またはオブジェクト定義のエラーが発生しました。

VBA関数からVBA関数が呼び出された同じワークシートへの書き込みは許可されていませんか?

4

1 に答える 1

3

これは、Excel の組み込みの動作です。ワークシートから呼び出される関数 (Excel 用語では UDF と呼ばれることが多い - ユーザー定義関数) は、値を返す以外にワークシートに対して何もできません。

ただし、上記のコードには別のエラーがあるようです。

Set destination.Value = ChannelCode 

オブジェクト変数をオブジェクト参照に設定するための構文を使用しているため、失敗するはずです。そこにエラーハンドラーがあれば、エラーをキャッチします。(Excel は、エラーを未処理のままにする UDF を終了するだけです。) 行は次のようになります。

destination.Value = ChannelCode 

ただし、UDF がセルに副作用を与えないという規則のため、ルーチンはその時点でまだ失敗します。エラー ハンドラがあったとしても、それはキャッチされないことに注意してください。UDF がセルを変更しようとしても、VBA はエラーを発生させません。UDF を停止して #VALUE を返すだけです。エラー。

あなたの場合、呼び出し元のセルの右と下のセルを変更しようとする代わりに、必要な値を含む配列を返すように関数を書き直すことができるようです。(または、UDF の代わりにマクロから関数を呼び出すこともできます。)

編集:

GetRows配列を返す限り、RecordSet から配列を返す ADO メソッドがあります。

コード批評 - 私は Rube Goldberg マシンを作成していますか?

于 2010-12-07T18:37:19.467 に答える