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

您需要分两步执行此操作:

将您的模块更改为:

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

这样做是返回左上角单元格的值,然后在计算完成后填充其余部分。我写这个的方式假设一次只调用一个 FillHere 函数。如果您想同时重新计算多个变量,那么您将需要一组更复杂的全局变量。

一个警告是,当它填充其他单元格时,它不会关心它覆盖的内容。

编辑:如果您想在 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

如果您随后在工作表中选择两个相邻的单元格,输入=FillHere()并按 Control+Shift+Enter(应用为数组公式),那么您应该会看到所需的输出。

于 2009-05-11T11:16:12.653 回答
1

从根本上说,函数只能影响调用它的单元格。听起来您可能需要查看使用Worksheet_ChangeorWorksheet_SelectionChange事件来触发对预期范围内的单元格的修改。

于 2009-05-11T22:30:57.383 回答
0

您可以使用 2 阶段过程间接执行此操作:编写您的 UDF,以便它以足够持久的方式存储数据(例如全局数组)。然后有一个插件,其中包含在每个计算事件后触发的应用程序事件,查看 UDF 存储的任何数据,然后重写必要的单元格(如果适当,带有关于覆盖的警告消息)并重置存储的数据。

这样,用户不需要在他们的工作簿中有任何代码。

我认为(但不确定)这是彭博等使用的技术。

于 2009-05-13T10:22:56.870 回答