首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >当范围有50,000行要计算时,UDF完全无效

当范围有50,000行要计算时,UDF完全无效
EN

Stack Overflow用户
提问于 2019-09-20 16:52:24
回答 2查看 82关注 0票数 0

我在下面创建了一个UDF,希望它能很好地工作。其思想是计算变量的加权平均值(情况需要满足标准)。但是当范围包含50,000行时(例如A1:A50000),这个宏就死了。Excel只是在几个小时后继续运行,没有响应。我认为VBA中的数组足以处理50,000行。我在想,在使用了这么多行的情况下,是否有更好的方法进行计算。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function SurpAvg(code As String, per As String, var As String, _
                                        dt1 As Range, dt2 As Range)

Dim weight As Variant, fperiod As Variant, ftype As Variant, ann As Variant, surpx As Variant
Dim startdt As Date, enddt As Date
Dim pctL As Double, pctH As Double, surpL As Double, surpH As Double
Dim i As Long, j As Long, a() As Variant, b() As Variant, total As Double, totalWT As Double

ThisWorkbook.Activate

With Application
    weight = .Transpose(Range(code).Value)
    fperiod = .Transpose(Range("FY").Value)
    ftype = .Transpose(Range("FT").Value)
    ann = .Transpose(Range("ann").Value)
    surpx = .Transpose(Range("surpx").Value)
End With

startdt = dt1.Value
enddt = dt2.Value
pctL = Range("PctL")
pctH = Range("PctH")
surpL = -Range("MaxSurp")
surpH = Range("MaxSurp")

i = -1
On Error GoTo ErrorHandler
For j = LBound(surpx) To UBound(surpx)
    If ftype(j) = var And ann(j) > startdt And ann(j) <= enddt And _
       IsNumeric(1 / weight(j)) And IsNumeric(1 / surpx(j)) And _
       surpx(j) > surpL And surpx(j) < surpH Then

        If InStr(fperiod(j), per) Then
            i = i + 1
            ReDim Preserve a(i) As Variant
            ReDim Preserve b(i) As Variant
            a(i) = surpx(j)
            b(i) = weight(j)
        End If
    End If
NextJ:
Next j
ErrorHandler:
If Err Then Resume NextJ

surpL = WorksheetFunction.Percentile(a, pctL)
surpH = WorksheetFunction.Percentile(a, pctH)

total = 0: totalWT = 0
For j = LBound(a) To UBound(a)
    totalWT = totalWT + b(j)
    If a(j) < surpL Then
        total = total + surpL * b(j)
    ElseIf a(j) > surpH Then
        total = total + surpH * b(j)
    Else
        total = total + a(j) * b(j)
    End If
Next j
SurpAvg = total / totalWT
End Function
EN

回答 2

Stack Overflow用户

发布于 2019-09-20 18:02:37

您很可能面临由错误处理导致的无限goto循环,因为过程中唯一的On Error语句在代码底部执行失败时仍然有效。

邦迪解决方案:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ErrorHandler:
If Err.Number <> 0 Then Resume NextJ

On Error GoTo ErrHandler

surpL = WorksheetFunction.Percentile(a, pctL)
surpH = WorksheetFunction.Percentile(a, pctH)

total = 0: totalWT = 0
For j = LBound(a) To UBound(a)
    totalWT = totalWT + b(j)
    If a(j) < surpL Then
        total = total + surpL * b(j)
    ElseIf a(j) > surpH Then
        total = total + surpH * b(j)
    Else
        total = total + a(j) * b(j)
    End If
Next j
SurpAvg = total / totalWT
ErrHandler:
End Function

这很糟糕,因为我们甚至没有费心去找出问题出在哪里,因为它用适当的流控制代替了错误处理。如果存在逻辑错误(例如,我们忽略的错误是一些下标超出范围的错误),那么这种错误处理会阻止错误浮出水面,并使调试变得比需要的困难得多。

一个真正的解决方案应该首先避免处理错误。例如,通过消除假设:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
If totalWT <> 0 Then SurpAvg = total / totalWT

当您使用On Error GoTo {label}时,您应该以这样一种方式编写代码:只有在错误状态下才能访问{label}

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Public Sub DoSomething()
    On Error GoTo ErrHandler
    '...
    Exit Sub '<~ end of "happy path"
ErrHandler: '<~ begin "error path"
    '...
End Sub
票数 1
EN

Stack Overflow用户

发布于 2019-09-23 11:03:13

我之所以把它放在这里,是因为评论太长了,虽然我只是在模仿@Mathieu Guindon反复建议的,但如果它能让你走上正确的道路,那么它是值得重复的。

我理解为什么你想要好的错误处理,但你却把注意力集中在错误的方面。如果你不能很好地处理你的错误,你就不可能有好的错误处理。

想一想这对意味着什么

...去掉假设...还有..。使操作以某些特定条件为条件...

以及它如何帮助您

...找出问题所在..。

因为,所以使用

...用适当的流控制代替错误处理...

的主要问题是

...防止bug浮出水面,并使调试变得比需要的困难得多。

我缩小了你的代码范围,只关注一个变量。查看它,看看您是否可以找到在处理程序控制之前没有消除的任何假设,在特定条件下没有完成的任何操作,以及您的代码是否识别或防止了任何错误。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function SurpAvg([...])
    Dim surpx As Variant
    [...]
    ThisWorkbook.Activate
    [...]
        surpx = .Transpose(Range("surpx").Value)
    [...]
    On Error GoTo ErrorHandler
    For j = LBound(surpx) To UBound(surpx)
        [...]
    NextJ:
    Next j
    ErrorHandler:
    If Err Then Resume NextJ
    [...]
    End Function

我看到的唯一被消除的假设是那些被消除为默认处理程序的假设。控制权在没有任何前提条件的情况下交给你的处理程序,甚至工作簿都是用ThisWorkbook.Activate来假定的。假设ActiveWorkbook没有调用外部代码。如果它由外部代码调用(通常使用Personal.xlsb或*.xlam加载项),则您将使用错误的工作簿;请考虑'Workbook1'Sheet1!A1包含承载在Personal中的自定义项,使用ThisWorkbook表示该函数返回从Personal中的数据派生的值,而不是从'Workbook1'Sheet1!A1中派生的值

仔细看一下:surpx = .Transpose(Range("surpx").Value)这一行是在将控制权分配给错误处理程序之前执行的,所以这里的错误是由缺省处理程序处理的;但是它不能捕获逻辑错误,并且您可能在这里有一个语法正确的错误,但仍然会在代码中进一步导致运行时错误,或者可能导致不准确的结果。例如:

  • Range("surpx")未显式限定。命名范围surpx的作用域可以是工作簿以及工作簿中任意数量的单个工作表。您的代码假设活动工作表是正确的工作表,并且它会很高兴地接受意外的值,但如果范围不是exist.
  • Range("surpx").Value,那么默认处理程序至少会向您发出错误1004消息的警告。我喜欢div/0错误,所以考虑一下这个范围内的错误会发生什么。surpx是一个Variant,所以在您尝试将其与For j = LBound(surpx) To UBound(surpx)一起使用之前,它很乐意接受"Error 2007“的值,没有任何问题。这是您向处理程序授予权限后的第一行代码,因此默认处理程序无法帮助您,并且不会尝试防止、纠正或提供标识错误的信息。您的处理程序所做的唯一一件事就是默默地跳过一段代码。这是好的错误处理的对立面。

除了已经说过的,我的建议是,重新访问您的数据类型以删除变体,真正地考虑如何调用这段代码,显式地限定您的对象,尽管已经说过了,但值得再重复一遍,在启用自定义处理程序之前,使用默认处理程序来调试程序。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58032418

复制
相关文章
【C++】命名空间 namespace 与 标准流 iostream ( 命名空间概念简介 | 命名空间定义 | 命名空间使用 | iostream 中的命名空间分析 )
命名空间 namespace 又称为 名字空间 , 名称空间 , 名域 , 作用域 , 是 C++ 语言 对 C 语言 的扩展 之一 ;
韩曙亮
2023/10/15
8240
【C++】命名空间 namespace 与 标准流 iostream ( 命名空间概念简介 | 命名空间定义 | 命名空间使用 | iostream 中的命名空间分析 )
命名空间介绍之六:用户命名空间的延伸
本文中,继续上周关于用户命名空间的讨论。特别的,我们看一下更多有关与用户命名空间、capabilities 的交互及用户命名空间与其它类型的命名空间的结合。本文是命名空间系列的最后一篇。
谛听
2019/11/02
1.9K0
命名空间介绍之六:用户命名空间的延伸
命名空间介绍之四:PID 命名空间的延伸
在本文中,我们将继续上周关于 PID 命名空间的讨论(并扩展我们正在进行的关于命名空间的系列文章)。PID 命名空间的一个用途是实现一个进程包(容器),其行为类似于一个自包含的 Linux系统。init 进程是传统系统和 PID 命名空间容器的关键部分。因此,我们将研究 init 进程的特殊角色,并着重于它与传统 init 进程不同的几个方面。此外,我们还将研究命名空间 API 应用于 PID 命名空间时的一些其他细节。
谛听
2019/10/30
2.2K0
命名空间介绍之四:PID 命名空间的延伸
命名空间
c++基础_命名空间namespace 命名空间是用来组织和重用代码的编译单元 在编写代码时写的程序不可能所有的标识符都没有重名现象, 在多人协作开发时更加不可控, 尤其对于库来说问题更加严重. 为了解决重名现象, 通过命名空间来避免冲突! ---- 命名空间的定义: namespace 命名空间标识符 { ...命名空间成员(普通变量成员,函数成员,类成员...) } 注意: 命名空间标识符必须满足标识符命名规则和命名规范, 习惯名字唯一, 通常以开发团队的名字(项目名) 来命名. 命名
木杉乀
2021/05/06
1.4K0
命名空间介绍之七:网络命名空间
自从上次我们研究 Linux 命名空间以来已经有一段时间了。我们的系列缺少了一篇,现在补上:网络命名空间。顾名思义,网络命名空间将网络设备、地址、端口、路由、防火墙规则等的使用划分在不同的盒子,基本上是在一个单独运行的内核实例中虚拟化网络。网络命名空间在 2.6.24 版进入内核,约 5 年前;大概一年后,它们才进入黄金时段。从那以后,它们似乎在很大程度上被开发人员忽略了。
谛听
2019/11/03
3.5K0
命名空间介绍之七:网络命名空间
命名空间介绍之三:PID 命名空间
接着前两篇命名空间文章,现在看一下 PID 命名空间。与 PID 命名空间相关的全局资源就是进程 ID 数字空间。这意味着在不同 PID 命名空间中的进程可以有相同的进程 ID。PID 命名空间实现的容器可在主机之间迁移,并保持容器内的进程 ID 不变。
谛听
2019/10/29
3.5K0
命名空间介绍之三:PID 命名空间
命名空间介绍之五:用户命名空间
继续我们的命名空间系列文章,本文看一下用户命名空间,大部分实现于 Linux 3.8。(剩余的工作是 XFS 和其它文件系统中的一些改动;后者合并于 3.9)。用户命名空间与用户和组 ID 相映射。这意味着一个进程在某个用户命名空间内的用户和组 ID 可以与用户命名空间外的不同。最重要的是,一个进程可以在一个命名空间外有一个非 0 的用户 ID ,同时在命名空间内有一个为 0 的用户 ID;换句话说,进程在一个用户命名空间外没有特权,但在用户命名空间内有 root 特权。
谛听
2019/11/01
3.4K0
命名空间介绍之五:用户命名空间
PHP的命名空间
命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:
老雷PHP全栈开发
2020/07/02
1.9K0
python的命名空间
在Python中,所有的名字都存在一个空间中,它们在该空间中存在和被操作——这就是命名空间。它就像一个盒子,每一个变量名字都对应装着一个对象。当查询变量的时候,会从该盒子里面找到相应的对象。
狼啸风云
2019/09/18
9550
PHP命名空间
概述 什么是命名空间呢? 这个概念我第一次知道是在C++中. 首先, 为什么要用到命名空间呢? 当然是为了解决重名的问题了, 其实命名空间和Java中的包有着异曲同工之妙, Java中 a包下的Tes
烟草的香味
2019/07/25
2.3K0
PHP命名空间
js命名空间
start和stop在car下以名称空间命名:car.start()和car.stop()。
IT工作者
2021/12/29
1.7K0
PHP命名空间
本文是复习所写,并不会涵盖一些基础知识点 定义 命名空间就相当于操作系统中目录的概念 主要是为了解决以下两个问题: 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突 为很
码一
2022/06/06
2.5K0
PHP命名空间
Kubernetes命名空间
Kubernetes中提供了命名空间,但是如果你的团队规模比较小并且集群规模也不大,完全可以不用Namespaces而使用labels来区分不同的资源,随着项目增多、集群规模扩大、人员的增加,你才需要使用Namespaces,通过namespace你可以创建多个虚拟的集群。
大江小浪
2018/09/19
2.3K0
python命名空间
ke1th
2018/01/02
1.5K0
Swift中的命名空间
命名空间namespace在C++、C#里面是一个常见概念,Swift中也引入了这样一个机制,下面来探索一下这个命名空间的来龙去脉。
YungFan
2018/12/26
2.3K0
特殊的 x 命名空间
为什么叫它特殊呢,因为x命名空间中的东西是用来服务整个xaml页面的,通过这个命名空间中的工具,可以去扩充xaml的功能,或者帮助我们更好的开发xaml页面。
宿春磊Charles
2021/11/05
5970
Namespace(命名空间)的使用
作者:飞刀 关于Namespace(命名空间)的使用常用,这是在引用M$为我们提供的Namespa数据库
Java架构师必看
2020/10/26
1.1K0
【C++ 语言】命名空间 ( namespace | 命名空间定义 | 命名空间嵌套 | 域作用符 | 与 include 对比 )
在 C++ 代码中 , 经常遇到 #include "c_extern.h" 和 using namespace std; 代码 , 两种方式都可以声明可使用的若干变量和方法 ;
韩曙亮
2023/03/27
2.3K0
【C++ 语言】命名空间 ( namespace | 命名空间定义 | 命名空间嵌套 | 域作用符 | 与 include 对比 )
命名空间介绍之八:挂载命名空间和共享子树
挂载命名空间是创建每-用户和每-容器文件系统树的强大而灵活的工具。本文中,我们将仔细研究共享子树特性,它可通过自动、可控的方式在挂载命名空间之间传播挂载和卸载事件。
谛听
2019/11/03
4.1K0
命名空间介绍之八:挂载命名空间和共享子树
点击加载更多

相似问题

我得到命名空间错误

13

如果我有使用abc命名空间的应用程序,如何更改命名空间?

24

命名空间错误‘不是命名空间名称’

10

我如何修复这个‘命名空间找不到错误’?

13

发亮的应用程序错误shinyBS

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文