我不希望我的Excel加载项返回一个数组(而是我需要一个UDF来更改其他单元格)

Der*_*rek 4 c++ arrays excel add-in excel-addins

我已经创建了一个Excel加载项,并且这个加载项的功能之一,可以说New_Years当前需要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将根据需要填写下面的正方形和适当的日期.任何人都知道这是否可行?还是不可能?

非常感谢!

bre*_*tdj 14

它实际上可能是复杂的.我将来自Kevin Jones又名Zorvek的这件魔法重新发布,因为它位于EE Paywall后面(如果有人有权访问,则附上链接)

虽然Excel严格禁止UDF更改任何单元格,工作表或工作簿属性,但是当使用Windows计时器和Application.OnTime计时器依次调用UDF时,有一种方法可以实现此类更改.Windows计时器必须在UDF中使用,因为Excel忽略UDF中的任何Application.OnTime调用.但是,因为Windows计时器有限制(如果正在编辑单元格或对话框打开时,如果Windows计时器尝试运行VBA代码,Excel将立即退出),它仅用于计划Application.OnTime计时器,安全计时器如果未编辑单元格且未打开任何对话框,则Excel仅允许触发.

下面的示例代码说明了如何从UDF内部启动Windows计时器,如何使用该计时器例程启动Application.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
Run Code Online (Sandbox Code Playgroud)