3

VBA 関数からスプレッドシートのセルを埋めたいだけです。たとえば、セルに =FillHere() と入力すると、いくつかのセルにデータが入力されます。

私はそのような機能で試しました:

Function FillHere()
  Dim rngCaller As Range
  Set rngCaller = Application.Caller
  rngCaller.Cells(1, 1) = "HELLO"
  rngCaller.Cells(1, 2) = "WORLD"
End Function

範囲を変更しようとするとすぐに壊れます。次に、これを試しました(実際に探している動作ではありません):

Function FillHere()
    Dim rngCaller As Range
    Cells(1, 1) = "HELLO"
    Cells(1, 2) = "WORLD"
End Function

これも機能していません。しかし、F5 を使用して VBA からこの関数を開始すると機能します。関数の呼び出し中にスプレッドシートで何かを変更することはできないようです...一部のライブラリはそれを行います...

また、関数から配列を返すことも試みました (実際、これが最初のアイデアでした)。問題は、配列の最初の要素しか取得できないことです (左上隅の数式 + F2 + CTRL-SHIFT-ENTER で領域全体を選択することを暗示するトリックがありますが、それはユーザーが知る必要があることを意味します)配列のサイズを事前に)。

私は本当にこの問題で立ち往生しています。私は最終的なエンドユーザーではないので、できればまったく引数のない、非常に使いやすいものが必要です。

PS: 申し訳ありませんが、既にこの質問をしてしまいましたが、その時点では登録されておらず、もう他のスレッドに参加できないようです。

4

4 に答える 4

3

これは、次の 2 つの手順で行う必要があります。

モジュールを次のように変更します。

Dim lastCall As Variant
Dim lastOutput() As Variant

Function FillHere()
    Dim outputArray() As Variant
    ReDim outputArray(1 To 1, 1 To 2)
    outputArray(1, 1) = "HELLO"
    outputArray(1, 2) = "WORLD"

    lastOutput = outputArray
    Set lastCall = Application.Caller

    FillHere = outputArray(1, 1)
End Function

Public Sub WriteBack()
    If IsEmpty(lastCall) Then Exit Sub
    If lastCall Is Nothing Then Exit Sub

    For i = 1 To UBound(lastOutput, 1)
        For j = 1 To UBound(lastOutput, 2)
            If (i <> 1 Or j <> 1) Then
                lastCall.Cells(i, j).Value = lastOutput(i, j)
            End If
        Next
    Next

    Set lastCall = Nothing
End Sub

次に、Sub を呼び出すために、VBA の ThisWorkbook 領域に移動し、次のようなものを追加します。

Private Sub Workbook_SheetCalculate(ByVal Sh As Object)
    Call WriteBack
End Sub

これが行うことは、左上のセルの値を返し、計算が完了した後に残りを入力することです。私がこれを書いた方法は、一度に 1 つの FillHere 関数だけが呼び出されることを前提としています。同時に再計算する複数の変数が必要な場合は、より複雑なグローバル変数のセットが必要になります。

警告の 1 つは、他のセルに値を入力するときに何を上書きしてもかまわないということです。

編集:XLAでアプリケーション全体でこれを行いたい場合。ThisWorkbook 領域のコードは次のようになります。

Private WithEvents App As Application

Private Sub App_SheetCalculate(ByVal Sh As Object)
    Call WriteBack
End Sub

Private Sub Workbook_Open()
    Set App = Application
End Sub

これにより、アプリケーション レベルの計算が結び付けられます。

于 2009-05-14T09:06:09.383 に答える
1

あなたがしようとしていることは、Excel では機能しません。これは仕様によるものです。

ただし、これを行うことができます:

Function FillHere()
    Redim outputArray(1 To 1, 1 To 2)
    outputArray(1, 1) = "HELLO"
    outputArray(1, 2) = "WORLD"
    FillHere = outputArray
End Function

次に、ワークシートで隣接する 2 つのセルを選択し、=FillHere()Enter キーを押して Control+Shift+Enter キーを押すと (配列数式として適用されます)、目的の出力が表示されます。

于 2009-05-11T11:16:12.653 に答える
1

基本的に、関数は呼び出し元のセルにのみ影響を与えることができます。Worksheet_ChangeまたはWorksheet_SelectionChangeイベントを使用して、意図した範囲のセルの変更をトリガーする必要があるようです。

于 2009-05-11T22:30:57.383 に答える
0

これは、2 段階のプロセスを使用して間接的に行うことができます。データを十分に永続的な方法 (グローバル配列など) で格納するように UDF を記述します。次に、各計算イベントの後に起動するアプリケーション イベントを含むアドインを用意し、UDF によって格納されたデータを調べてから、必要なセルを書き換え (必要に応じて上書きに関する警告メッセージを表示して)、格納されたデータをリセットします。

この方法では、ユーザーはワークブックにコードを含める必要はありません。

ブルームバーグなどで使われている手法だと思います(確かなことはわかりませんが)。

于 2009-05-13T10:22:56.870 に答える