- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这个问题可能对许多 VBA 程序员有用。它涉及实现两个有用的独立任务并使它们同时工作。
第一个任务是为 UDF 制作 Excel 函数工具提示。虽然似乎还没有找到明确的解决方案,但目前我对自定义插入函数向导的解决方案感到满意。您可以在此处找到有关实现自定义插入函数向导的方法的主题:How to put a tooltip on a user-defined function 当我说插入函数向导时,我指的是这个窗口:
如果您也对有关寻求实现函数工具提示的明确解决方案的主题感兴趣,您可以访问此处:The quest for the Excel custom function tooltip
第二个任务是在调用 UDF 的不同单元中进行写入。我在这里找到了一个很好的解决方案:I don't want my Excel Add-In to return an array (instead I need a UDF to change other cells)
现在,问题来了:尝试同时执行这两个任务时,Excel 崩溃。我想让这两个任务在调用单个函数时工作,防止 excel 崩溃。我想对 UDF 使用自定义的插入函数向导,该向导可以在调用它的不同单元格中写入。我想这样做的原因是我正在编写一个带有带有多个输入参数的函数的插件(因此用户需要输入参数的工具提示)并且我需要在与它们被调用的单元格不同的单元格中写入(因为我不想坚持使用宏。我想要一个函数驱动的插件,而不是按钮驱动的插件)。对于熟悉 Bloomberg Excel API 的人来说,这几乎就是函数 BDH() 的作用。
我编写了两个模块作为解决该问题的指南。第一个构建了一个需要在运行 main 函数之前运行的 displayParameters() 函数。它通过函数驱动的方式执行自定义插入函数向导的任务。第二个函数是名为 sumTwoNumbers 的主函数,它执行两个数字的总和并将结果显示在与调用该函数的单元格不同的单元格中。当您尝试使用插入函数向导 ( ctr + A ) 运行第二个函数 ( sumTwoNumbers() ) 时,在自定义该函数后(运行 displayParameters() 后),Excel 将崩溃。
模块 1:
Option Explicit
Private Declare Function SetTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long _
) As Long
Private Declare Function KillTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long _
) As Long
Private mCalculatedCells As Collection
Private mWindowsTimerID As Long
Private mApplicationTimerTime As Date
Public Function displayParameters() As Variant
' This is a UDF that returns true when the volscore file is created and starts a windows timer
' that starts a second Appliction.OnTime timer that performs activities not
' allowed in a UDF. Do not make this UDF volatile, pass any volatile functions
' to it, or pass any cells containing volatile formulas/functions or
' uncontrolled looping will start.
displayParameters = "Success"
'Cache the caller's reference so it can be dealt with in a non-UDF routine
If mCalculatedCells Is Nothing Then Set mCalculatedCells = New Collection
On Error Resume Next
mCalculatedCells.Add Application.Caller, Application.Caller.Address
On Error GoTo 0
' Setting/resetting the timer should be the last action taken in the UDF
If mWindowsTimerID <> 0 Then KillTimer 0&, mWindowsTimerID
mWindowsTimerID = SetTimer(0&, 0&, 1, AddressOf AfterUDFRoutine1_displayParameters)
End Function
Public Sub AfterUDFRoutine1_displayParameters()
' This is the first of two timer routines. This one is called by the Windows
' timer. Since a Windows timer cannot run code if a cell is being edited or a
' dialog is open this routine schedules a second safe timer using
' Application.OnTime which is ignored in a UDF.
' Stop the Windows timer
On Error Resume Next
KillTimer 0&, mWindowsTimerID
On Error GoTo 0
mWindowsTimerID = 0
' Cancel any previous OnTime timers
If mApplicationTimerTime <> 0 Then
On Error Resume Next
Application.OnTime mApplicationTimerTime, "AfterUDFRoutine2_displayParameters", , False
On Error GoTo 0
End If
' Schedule timer
mApplicationTimerTime = Now
Application.OnTime mApplicationTimerTime, "AfterUDFRoutine2_displayParameters"
End Sub
Public Sub AfterUDFRoutine2_displayParameters()
' This is the second of two timer routines. Because this timer routine is
' triggered by Application.OnTime it is safe, i.e., Excel will not allow the
' timer to fire unless the environment is safe (no open model dialogs or cell
' being edited).
Dim sumTwoNumbersArgumentsDescription(1 To 2) As String
sumTwoNumbersArgumentsDescription(1) = "Write the first number of a Sum"
sumTwoNumbersArgumentsDescription(2) = "Write the second number of a Sum"
Application.MacroOptions Macro:="sumTwoNumbers", _
ArgumentDescriptions:=sumTwoNumbersArgumentsDescription
'Description:="describre the ivol function"
MsgBox ("The formal parameters and instance of actual parameters are now successfully displayed at the Insert Function Dialog Box.")
End Sub
模块 2:
Option Explicit
'This global variable is the way I found of passing the output of sumTwoNumbers into the
'function "AfterUDFRoutine2"
Dim outputGlobal As Variant
Private Declare Function SetTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long _
) As Long
Private Declare Function KillTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long _
) As Long
Private mCalculatedCells As Collection
Private mWindowsTimerID As Long
Private mApplicationTimerTime As Date
'Non-Volatile Function2
Public Function sumTwoNumbers(Optional ByVal param1 As Integer _
, Optional ByVal param2 As Integer _
) As Variant
sumTwoNumbers = param1 + param2
outputGlobal = sumTwoNumbers
sumTwoNumbers = "Success"
'Cache the caller's reference so it can be dealt with in a non-UDF routine
If mCalculatedCells Is Nothing Then Set mCalculatedCells = New Collection
On Error Resume Next
mCalculatedCells.Add Application.Caller, Application.Caller.Address
On Error GoTo 0
' Setting/resetting the timer should be the last action taken in the UDF
If mWindowsTimerID <> 0 Then KillTimer 0&, mWindowsTimerID
mWindowsTimerID = SetTimer(0&, 0&, 1, AddressOf AfterUDFRoutine1_sumTwoNumbers)
End Function
Public Sub AfterUDFRoutine1_sumTwoNumbers()
' This is the first of two timer routines. This one is called by the Windows
' timer. Since a Windows timer cannot run code if a cell is being edited or a
' dialog is open this routine schedules a second safe timer using
' Application.OnTime which is ignored in a UDF.
' Stop the Windows timer
On Error Resume Next
KillTimer 0&, mWindowsTimerID
On Error GoTo 0
mWindowsTimerID = 0
' Cancel any previous OnTime timers
If mApplicationTimerTime <> 0 Then
On Error Resume Next
Application.OnTime mApplicationTimerTime, "AfterUDFRoutine2_sumTwoNumbers", , False
On Error GoTo 0
End If
' Schedule timer
mApplicationTimerTime = Now
Application.OnTime mApplicationTimerTime, "AfterUDFRoutine2_sumTwoNumbers"
End Sub
Public Sub AfterUDFRoutine2_sumTwoNumbers()
' This is the second of two timer routines. Because this timer routine is
' triggered by Application.OnTime it is safe, i.e., Excel will not allow the
' timer to fire unless the environment is safe (no open model dialogs or cell
' being edited).
'Write the output to the sheet
Dim dest
Set dest = ActiveCell.Offset(0, 1)
dest.Value = outputGlobal
Set outputGlobal = Nothing
End Sub
到目前为止的进展
我发现每次您填写输入参数后,插入函数向导都会在后台运行您的函数,并在向导中看到的“=”后面输出结果。因此,如果在运行参数数量不足的函数时触发错误,则在向导中提供输入后也会触发该错误。如果在使用该数量的输入运行函数时显示消息框,则向导前面将显示一个消息框。但是,当您使用经过修改的 UDF 以便将输出写入调用它的不同单元格时,并且在通过向导填充输入时不会触发错误,Excel 将中断。我的猜测是,发生这种情况是因为您的函数在后台运行,触发 AfterUDFRoutine1_sumTwoNumbers(),然后触发 AfterUDFRoutine2_sumTwoNumbers()。当 AfterUDFRoutine2_sumTwoNumbers() 最终尝试在 Excel 电子表格中写入并且向导已打开时,Excel 会中断,因为在向导打开的情况下无法在单元格中写入。解决此问题的一个明显的解决方案是找到一种方法,使“插入函数向导”在提供每个输入参数后停止在后台运行该函数,并使其等到单击“确定”后运行该函数。
最佳答案
上面的问题太长了。我可以通过询问如何在能够修改其他单元格的 UDF 中使用“插入函数向导”来总结它。我一直坚持 UDF 的概念,它可以修改我所知道的其他单元格,并且没有跳出框框思考。可以执行此操作的 UDF 代码,如下所述:I don't want my Excel Add-In to return an array (instead I need a UDF to change other cells) ,当用户尝试使用“插入函数向导”时会破坏 Excel。此问题的解决方法是创建一个自动调整数组输出大小的 UDF,而不是创建修改外部单元的 UDF。我找到了这个插件:https://colinlegg.wordpress.com/2014/08/25/self-extending-udfs-part-1/它给出了一个名为“=rxlRESIZE()”的函数的实现,该函数可以调整数组输出的大小。如果您在代码中编写该函数,并在返回数组输出之前立即应用该函数,那么只要您的输出是数组,您就有一个可以写入其他单元格的 UDF。最后,这可以防止 Excel 在使用“插入函数向导”时崩溃。为了自定义插入函数向导,我仍然使用从这篇文章中获得的实现:How to put a tooltip on a user-defined function
关于vba - 寻求结合如何自定义 UDF 的插入函数向导和使 UDF 操作其他单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33137386/
我有一张 Excel 表格,用于更新玩家评分。 播放器 配售 初始化 1 2 3 4 金融评级 一个 1 2.0 1.000 0.018 0.016 0.014 2.007 D 2 -2.0 54.5
我有一个 map = std::map ,其中 myItemModel继承QAbstractItemModel . 我现在要合并所有 myItemModel合一myItemModel (其他所有元素模
我大量使用“do.call”来生成函数调用。例如: myfun <- "rnorm"; myargs <- list(n=10, mean=5); do.call(myfun, myargs); 但是
想象一下 InputStream 的以下变体: trait FutureInputStream { //read bytes asynchronously. Empty array means E
这是我的 C 代码: #include void sum(); int newAlphabet; int main(void) { sum();
我只是想选择类“.last”之后的每个元素。 HTML: 1 2 Jquery
我正在为一个项目构建一个 XML 反序列化器,我经常遇到这种类型的代码情况: var myVariable = ParseNDecimal(xml.Element("myElement")) == n
这是来自 Selecting the highest salary 的继续问题 假设有一个表 'wagetable' name lowhours highhours wage pri
我正在为我的程序创建一个战舰程序;该程序运行良好,但我试图确保当用户将坐标超出范围时,程序会说他们输入的坐标不正确。这是代码: #include #include void
我有一个函数,它为每种情况返回不同的 DWORD 值,如果出现错误。所以我有以下定义: #define ERR_NO_DB_CONNECTION 0x90000 #define ERR_DB_N
在派生类中引发基类事件以下简单示例演示了在基类中声明可从派生类引发的事件的标准方法。此模式广泛应用于 .NET Framework 类库中的 Windows 窗体类。在创建可用作其他类的基类的类时,应
我只是想知道这是否可能: use Modern::Perl; my @list = ('a' .. 'j'); map { func($_) } each(@list); sub func { m
我一直在使用 =IF(L2="","Active",IF(K2I2,"Late"))) 有效,但现在我需要检查 F 上的多个条件 专栏 我试过了 OR 函数 =IF(OR(F2="Scheduled"
我有 2 个命令,如下所示。 在视频中添加介绍图片 ffmpeg -y -loop 1 -framerate 10 -t 3 -i intro.png -i video.mp4 -filter_com
好的,我有这个公式可以根据名字和姓氏列表生成用户名。现在,虽然这可行,但我希望单元格改为引用我自己的 VBA 函数。但是,由于代码少得多,我仍然想使用原始公式。 我有这个公式: =SUBSTITUTE
我有两个 HAProxy 实例。两个实例都启用了统计信息并且工作正常。 我正在尝试将两个实例的统计信息合并为一个,以便我可以使用单个 HAProxy 来查看前端/后端统计信息。我试图让两个 hapro
我有一个 Observable,其中每个新值都应该引起一个 HTTP 请求。在客户端,我只关心最新的响应值;但是,我希望每个请求都能完成以进行监控/等。目的。 我目前拥有的是这样的: function
我的网站上有 TinyMCE 插件。在 TinyMCE 插件的 textarea 中添加图像时,我希望这些图像包含延迟加载。我网站的缩略图具有特定类型的延迟加载,其中 src 图像是灰色背景。根据用户
我希望合并润滑间隔,以便如果它们重叠,则从内部第一个时间获取最小值和从内部最后一个时间获取最大值并总结以创建一个跨越整个时间段的新间隔。这是一个reprex: library(lubridate, w
我有一个应用程序,它本质上是一个页眉、主要内容和一个始终可见的页脚。页脚可以改变大小,我想在页脚上方的主内容面板上放置一些工具。主要布局是用 flex 完成的,我阅读文档的理解是绝对定位通过相对于最近
我是一名优秀的程序员,十分优秀!