我不希望我的 Excel 加载项返回数组(相反,我需要 UDF 来更改其他单元格)
I don't want my Excel Add-In to return an array (instead I need a UDF to change other cells)
我创建了一个Excel外接程序,这个外接程序的一个函数,让我们说New_Years
目前需要2年的时间,并在这2年之间的每个新年日作为Excel中的数组输出。因此,New_Years(2000,2002)
将返回2000年1月1日、2001年1月1日和2002年1月1日的最后一个单元格。
问题是我必须知道在那个时间里有3个日期,选择3个单元格,在最上面的单元格中输入我的公式,然后按Ctrl + Shift + Enter
填充数组。
我使用XLW版本5将我的c++代码转换为.xll文件。我真的很希望,如果有某种方法,我可以用我的公式填写一个方形,Excel会在需要的时候用适当的日期填写下面的方形。有人知道这是可能的吗?还是不可能?
多谢!
这实际上是可能的,尽管很复杂。我重新发布了Kevin Jones aka Zorvek的这段魔法,因为它位于EE付费墙后面(如果有人有访问权限,请附上链接)
虽然Excel严格禁止UDF更改任何单元格,工作表,或工作簿属性时,有一种方法可以影响此类更改UDF是使用Windows计时器和应用程序调用的。OnTime定时器序列。Windows计时器必须在UDF中使用,因为Excel忽略任何应用程序。OnTime在UDF内调用。但是,因为Windows定时器有限制(Excel会立即退出,如果一个Windows计时器尝试运行VBA代码,如果正在编辑单元格或对话框打开),它仅用于调度应用程序。定时一个安全的计时器,Excel只允许在单元格被激活时触发未编辑且未打开对话框
下面的示例代码演示了如何从启动Windows计时器在UDF中,如何使用计时器例程启动一个应用程序。OnTime定时器,以及如何传递只有已知的信息将UDF传递给随后的定时器执行的例程。下面的代码必须是
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 AddTwoNumbers( _
ByVal Value1 As Double, _
ByVal Value2 As Double _
) As Double
' This is a UDF that returns the sum of two numbers 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.
AddTwoNumbers = Value1 + Value2
' 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)
End Function
Public Sub AfterUDFRoutine1()
' 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", , False
On Error GoTo 0
End If
' Schedule timer
mApplicationTimerTime = Now
Application.OnTime mApplicationTimerTime, "AfterUDFRoutine2"
End Sub
Public Sub AfterUDFRoutine2()
' 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 Cell As Range
' Do tasks not allowed in a UDF...
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Do While mCalculatedCells.Count > 0
Set Cell = mCalculatedCells(1)
mCalculatedCells.Remove 1
Cell.Offset(0, 1).Value = Cell.Value
Loop
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
多亏了本页早些时候的文章,我才能够创建一种易于使用的模块。
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' POST UDF UPDATING MODULE v.9.2020 cdf
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Since Excel won't allow UDFs to update any other cells,
' an API timer is used to trigger a post UDF subroutine.
'
' This acts like a recalculate. Your code should recalculate the entire
' sheet. Tried to get it to work with a specific range, but, with all
' the different update variations ({Enter}, {Tab}, {Backspace}, {Delete},
' mouse click in the middle of an update, etc.), no luck. Any ideas?
'
' Originally, before the slight tweak, the code was found here:
' https://stackoverflow.com/questions/8520732/
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' HOW TO USE
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'
' Create a module (in the Modules folder) and copy this entire document
' into it.
'
'
' Code this code into your UDF's subroutine in your module (in Modules
' folder) (should be close to the end of the code):
'
' ' Use Post UDF Timer to update other cells.
' Call TimerModulesName.SetAPITimer("UDFModule.PostUDFRoutine")
'
'
' Edit the code names:
'
' Change TimerModulesName to the module you copied this document into.
' UDFModule to the module your post UDF subroutine is in.
' PostUDFRoutine to your post UDF subroutine.
'
' Example: Module4.SetAPITimer("Module1.UpdateMyCells")
'
'
#If VBA7 Then
Private Declare PtrSafe Function SetTimer Lib "user32" ( _
ByVal hwnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As LongLong _
) As Long
Private Declare PtrSafe Function KillTimer Lib "user32" ( _
ByVal hwnd As Long, _
ByVal nIDEvent As Long _
) As Long
#Else
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
#End If
Private mCalculatedCells As Collection
Private mWindowsTimerID As Long
Private mApplicationTimerTime As Date
Private mRoutine As String
Public Sub SetAPITimer(sRoutine As String)
' 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.
' 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)
' Set Post UDF module and routine
mRoutine = sRoutine
End Sub
Private Sub AfterUDFRoutine1()
' 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", , False
On Error GoTo 0
End If
' Schedule timer
mApplicationTimerTime = Now
Application.OnTime mApplicationTimerTime, "AfterUDFRoutine2"
End Sub
Private Sub AfterUDFRoutine2()
' 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).
' Do tasks not allowed in a UDF... (post UDF code)
Application.Run mRoutine
End Sub
- 将QIcon添加到QTableView单元格
- 当用户在qtablewidget中输入单元格时,如何获得信号?C++
- 查找矩阵中单元格的相邻元素
- C++:在多个线程中访问同一数组/向量的不同单元格是否会产生数据竞赛?
- 当我使用需要计算数组单元格地址的模板时,奇怪的C++行为
- PyQT - 在 QTableWidget 单元格中显示垂直文本
- 2D 数组,某些单元格保存特定数据
- 为什么通过定义另一个指针单元格,整个代码停止工作?
- CLI/C++dataGridView示例-设置comobox单元格列表的索引
- 用单元格表示迷宫
- 为什么不能使用 setData() 在 QTreeView 中设置单元格的背景颜色?
- 将 GtkTreeView 中的单元格设置为以编程方式编辑模式
- 如何防止Qt中的当前单元格更改信号或跳过"processing"?
- 将当前多边形数据单元与下一个多边形单元格 - VTK 进行比较
- VTK:尝试使用 vtkrubberbandpick&vtkHardwareSelector 选择区域中的可见单元格
- QTableWiget::cellChanged 信号不会为具有 QTableWidgetItem 的单元格发出
- 当存在空单元格时,用于 c++ 的 Tsv 文件解析器会突然结束
- C++ unordered_map<T,int> 如何区分空单元格和 0
- 基于单元格代替QTableWidget中的一行
- 我不希望我的 Excel 加载项返回数组(相反,我需要 UDF 来更改其他单元格)