Vba 打开或保存Excel时要触发的公式

Vba 打开或保存Excel时要触发的公式,vba,excel,Vba,Excel,我的Excel中有几个自定义(VBA)公式。例如 = isfileExists(c3) = isReadOnly(c3) 对这些函数有多个调用(200/列) 这些都会减慢文件的速度,因为它们涉及大量的VBA。我希望以上公式只在用户打开文件或仅保存文件时运行 如何在不触碰“启用/禁用自动计算”的情况下继续执行此操作?(请注意,我确实知道如何编写事件函数,但我正在寻找将其放入其中/任何地方的想法) 我的示例想法是,在公式前面添加一个,,每当用户打开/保存时,就会使用宏删除,(撇号)

我的Excel中有几个自定义(VBA)公式。例如

    = isfileExists(c3)
    = isReadOnly(c3)
对这些函数有多个调用(200/列)

这些都会减慢文件的速度,因为它们涉及大量的VBA。我希望以上公式只在用户打开文件或仅保存文件时运行

如何在不触碰“启用/禁用自动计算”的情况下继续执行此操作?(请注意,我确实知道如何编写事件函数,但我正在寻找将其放入其中/任何地方的想法)

我的示例想法是,在公式前面添加一个
,每当用户打开/保存时,就会使用宏删除
(撇号);因此,这些公式将进行计算。还有其他更简单的建议吗


多谢

您可以将公式结果缓存在全局(或函数内部的静态)字典对象中:一旦您检查了文件,就可以使用缓存的结果而不是重复文件检查)

公共函数ExpensiveCheck(fpath作为字符串)作为布尔值
静态dict作为对象,ans作为布尔值
'如果尚未创建词典,请创建词典
如果dict什么都不是,那么
Set dict=CreateObject(“scripting.dictionary”)
如果结束
如果不存在dict.exists(fpath),则
ans=(Dir(fpath,vbNormal)“”)在此处进行检查
添加路径,ans
如果结束
ExpensiveCheck=dict(fpath)
端函数
会话结束时,dict将丢失,因此在打开文件时,公式应始终刷新缓存


缺点是,如果要在检查的文件发生某些更改后更新输出,则可能需要某种机制来清除/刷新缓存。

您可以将公式结果缓存在全局(或函数内部的静态)中dictionary对象:检查文件后,可以使用缓存结果,而不是重复文件检查)

公共函数ExpensiveCheck(fpath作为字符串)作为布尔值
静态dict作为对象,ans作为布尔值
'如果尚未创建词典,请创建词典
如果dict什么都不是,那么
Set dict=CreateObject(“scripting.dictionary”)
如果结束
如果不存在dict.exists(fpath),则
ans=(Dir(fpath,vbNormal)“”)在此处进行检查
添加路径,ans
如果结束
ExpensiveCheck=dict(fpath)
端函数
会话结束时,dict将丢失,因此在打开文件时,公式应始终刷新缓存


缺点是,如果要在检查的文件发生某些更改后更新输出,则可能需要某种机制来清除/刷新缓存。

如果不希望自定义项与工作表的其余单元格一起计算,则不需要自定义项;将它们设置为
Private
,或将
选项Private Module
粘贴在声明它们的标准模块的顶部,以使它们不可用作自定义工作表函数

然后处理
工作簿。打开
工作簿。在保存
事件之前,让这两个处理程序调用一些
私有子
,该子子负责写入当前包含这些自定义项的单元格

这样,只有在工作簿打开并保存之前,才会计算这些值


导致磁盘I/O的自定义项并不理想:将这种处理保留在宏中。

如果不希望自定义项与工作表的其余单元格一起计算,则不需要自定义项;将它们设置为
Private
,或将
选项Private Module
粘贴在声明它们的标准模块的顶部,以使它们不可用作自定义工作表函数

然后处理
工作簿。打开
工作簿。在保存
事件之前,让这两个处理程序调用一些
私有子
,该子子负责写入当前包含这些自定义项的单元格

这样,只有在工作簿打开并保存之前,才会计算这些值


导致磁盘I/O的UDF并不理想:对宏保持这种处理。

我不明白,你为什么反对事件?这似乎是最简单的方法。您可以将公式结果缓存在全局(或函数中的静态)字典对象中:一旦您检查了文件,就可以使用缓存结果而不是重复文件检查)C3(etc)的内容是否经常更改?除非您将函数设置为Volatile,否则只应在引用的单元格更改时调用函数。我不明白,您为什么反对事件?这似乎是最简单的方法。您可以将公式结果缓存在全局(或函数中的静态)字典对象中:一旦您检查了文件,就可以使用缓存结果而不是重复文件检查)C3(etc)的内容是否经常更改?除非您将函数设置为Volatile,否则只应在引用的单元格更改时调用函数。这太棒了,但我对访问文件系统的UDF有复杂的感觉。无论如何,这是管理这些问题的一种方法(如果我理解正确的话)-确保只检查一次…这很好,但我对访问文件系统的UDF有复杂的感觉。不管怎样,进行一次投票。这是处理这些问题的一种方法(如果我理解正确的话)-确保只检查一次…谢谢大家。我将按照Mat的方式,将整个UDF移到宏端,使其穿过列并写入值。明天我一定会仔细看看蒂姆的答案,然后再试试看。此文件是共享驱动器中的共享文件,所有类型的人都可以访问此文件,因此这对它有一定的影响。谢谢大家。我将按照Mat的方式,将整个UDF移到宏端,使其穿过列并写入值。我一定会仔细看看Ti
Public Function ExpensiveCheck(fpath As String) As Boolean

    Static dict As Object, ans As Boolean
    'create the dictionary if not already created
    If dict Is Nothing Then
        Set dict = CreateObject("scripting.dictionary")
    End If

    If Not dict.exists(fpath) Then
        ans = (Dir(fpath, vbNormal) <> "") 'do your checking here
        dict.Add fpath, ans
    End If

    ExpensiveCheck = dict(fpath)
End Function