必须声明标量变量_Excel VBA解读(136): 在用户定义函数中的变体、引用、数组、计算表达式、标量...

学习Excel技术,关注微信公众号:

excelperfect

在前面的几篇文章中,我们自定义的函数使用定义为Range的参数来从Excel工作表中获取数据,例如:

Function VINTERPOLATEB(Lookup_Value As Variant, _

   Table_Array As Range, _

   Col_Num As Long)

如果在公式中使用单元格区域作为参数来调用该函数,运转得非常好:

=VINTERPOLATEB($H1,$A$1:$C$10000,2)

但是,如果使用计算表达式或者一组常量作为参数,则返回的结果为#Value:

{=VINTERPOLATEB($H1,($A$1:$C$10000*1),2)}

这个公式是数组公式,因此输入完后按Ctrl+Shift+Enter组合键,Excel自动在公式两边添加花括号。

=VINTERPOLATEB(4.5,{1,3,3.5;4,4,4.5;5,4.5,5},2)

这个公式使用了3行3列的数组常量。

Excel在调用函数之前会检测到这些参数不是单元格区域。

通过将参数定义为Variant型而不是Range可以解决此问题:Variant型参数几乎可以包含任何内容!但用户自定义函数现在必须处理Variant可能包含的所有不同类型的数据。

一种简单的方法是将参数声明为Variant型变量:这会将所有内容强制转换为值:

Function TestFunc(theParameter AsVariant)

   Dim vArr As Variant

   vArr = theParameter

   TestFunc = vArr

End Function

在VBE中,在赋值给函数的返回值的语句行设置断点,如下图1所示

6843423beceaa9490e2a13ab8b324325.png

图1

输入数组公式:

=TestFunc($A$1:$A$5*1)

本地窗口显示如下图2所示。

c1895ca1f1f75b156fc51c2412d0bc35.png

图2

在本地窗口可以看到,vArr变量包含2维Variant型数组,子类型为Double。

输入公式:

=TestFunc({1,2,3;5,6,7})

在本地窗口中可以看到其结果也是2维数组:

24385751101ce291d9d859e52d17946b.png

图3

输入公式:

=TestFunc({1,2,3})

在本地窗口可以看到结果为1维数组:

00f814cceb43761f2e5d6c7cd52eaec2.png

图4

输入公式:

=TestFunc({1;2;3})

在本地窗口可以看到结果为2维数组:

03ad1cc776e27f92ddb4825f658b1d1e.png

图5

输入公式:

=TestFunc(15)

可以看到结果为一个标量,而非数组:

6f3ca18a2420ee23aaf7c2f210e2f67a.png

图6

如果提供单元格区域作为函数参数:

=TestFunc($A$1:$A$5)

则得到:

9d96d3ad9370fe333a643bbcead60a62.png

图7

注意,theParameter变量包含对象子类型Range,意味着必须将它视为Range变量,而vArr包含从该Range变量中提取的值。

因此,在通用目的的用户自定义函数中,希望使用Variant型参数,并且经常需要确定变体的类型以及上限和下限。

为了获得最大效率,不能只使用vArr=theVariant,因为:

  • 不能使用.Value2,因为它可能不是单元格区域。

  • 在许多情况下,希望在强制转换所有值之前操控Range对象或者操控Range对象而不是强制转换所有值。

因此,这里有一个函数用来确定传递的内容以及它的大小:

Function Variant_Type(theVariantAs Variant)

   Dim jRowL As Long

   Dim jRowU As Long

   Dim jColL As Long

   Dim jColU As Long

   Dim jType As Long

   Dim varr As Variant

    '

    ' theVariant可以包含标量, 数组, 或单元格区域

    ' 找到上限和下限以及类型

    'type=1:单元格区域, 2:2维variant数组,

    ' 3:1-维variant数组(列的单行), 4:标量

    '

   On Error GoTo FuncFail

   jType = 0

   jRowL = 0

   jColL = 0

   jRowU = -1

   jColU = -1

   If TypeName(theVariant) = "Range" Then

        jRowL = 1

        jColL = 1

        jRowU = theVariant.Rows.Count

        jColU = theVariant.Columns.Count

        jType = 1

   ElseIf IsArray(theVariant) Then

        jRowL = LBound(theVariant, 1)

        jRowU = UBound(theVariant, 1)

        On Error Resume Next

        jColL = LBound(theVariant, 2)

        jColU = UBound(theVariant, 2)

        On Error GoTo FuncFail

        If jColU < 0 Then

            jType = 3

            jColL = jRowL

            jColU = jRowU

            jRowL = 0

            jRowU = -1

        Else

            jType = 2

        End If

   Else

        jRowL = 1

        jRowU = 1

        jColL = 1

        jColU = 1

        jType = 4

   End If

   Variant_Type = jType

   Exit Function

FuncFail:

   Variant_Type = CVErr(xlErrValue)

   jType = 0

   jRowU = -1

   jColU = -1

End Function

注意,首先测试变量是否包含Range,这是为了避免无意中将Range强制转换为其值。在确定变体的子类型时,VBA还有几种方法:

  • If TypeOf theVariant Is Range Then

  • If TypeName(theVariant) = “Range”Then

尝试使用VarType(theVariant)时要特别小心,这会对Range的覆盖范围进行强制转换,然后抛出结果值!

代码的图片版:

67990e16fd3ceda70fe6dea5f17864b2.png

小结:在通用目的的用户自定义函数中,必须使用Variant类型的参数而不是Range类型。可以通过在处理变量之前确定变体包含的内容来有效地处理出现的问题。

cf4cb223974149938f9f6464e2b4db25.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574123.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTMl5的存储方式sessionStorage和localStorage详解

html5中的Web Storage包括了两种存储方式&#xff1a;sessionStorage和localStorage。sessionStorage用于本地存储一个会话&#xff08;session&#xff09;中的数据&#xff0c;这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁因此sessionStorage不是…

mysql5.7四字节中文_mysql 字节问题,中文和数字

在mysql 5.1.5-alpha下测试得出如下结论latin1:1character1byte, 1汉字2character,也就是说一个字段定义成 varchar(200)&#xff0c;则它可以存储100个汉字或者200个字母。这一点要注意&#xff0c;尤其是当字段内容是字母和汉字组成时&#xff0c;尽量假设字段内容都是由汉字…

mysql 主主忽略错误_MySQL 主主报错: Fatal error: The slave I/O thread stops because master and slave have...

Mysql 主主启动错误处理error 信息&#xff1a;Slave_IO_State:Master_Host: 192.168.6.87Master_User: replicationMaster_Port: 3306Connect_Retry: 60Master_Log_File: mysql-bin.000003Read_Master_Log_Pos: 106Relay_Log_File: mysqld-relay-bin.000002Relay_Log_Pos: 4Re…

mysql内部_MySQL SQL语句内部剖析

一条SQL在MySQL体系结构内的执行流程:注意只有查询操作才会走查询缓存&#xff0c;而表的结构和数据发生改变时将会清空查询缓存。所以开启查询缓存的意义不大&#xff0c;8.0后已经废弃了该功能。一条update在存储引擎内部的执行步骤如下:SQL:update t set cc1 where id2;SQL完…

用Backbone.js创建一个联系人管理系统(四)

原文: Build a Contacts Manager Using Backbone.js: Part 4 这一系列教程的第四部分,教我们如何完成对已经存在的Contacts进行编辑和保存. 本教程是基于这一系列的前三个教程. 有不清楚的请先阅读前三部分. 开始 在Contact原模版里添加一个edit按钮. <button class"ed…

mysql默认时间怎么不同步_MYSQL 更新时间自动同步与创建时间默认值共存问题

本文作者&#xff1a;苏生米沿在使用SQL的时候&#xff0c;希望在更新数据的时候自动填充更新时间&#xff0c;那么在mysql中是如何实现的呢&#xff1f;如创建表usersCREATE TABLE RS_SIGNUPUSER (ID VARCHAR(36) COMMENT 主键(业务功能无关),USERNAME VARCHAR(50) COMMENT 姓…

HOJ-2662Pieces Assignment(状态压缩,动态规划)

Pieces Assignment Source : zhouguyue Time limit : 1 sec Memory limit : 64 M Submitted : 415, Accepted : 149 Background 有一个n*m的棋盘(n、m≤80,n*m≤80)要在棋盘上放k(k≤20)个棋子&#xff0c;使得任意两个棋子不相邻&#xff08;每个棋子最多和周围4个棋子相…

python代码技巧_让你python代码更快的3个小技巧

大家好&#xff01;今天呢&#xff0c;我们来聊一聊如何加速你的 python 代码。Python 语言的优点可以列举出许多&#xff0c;语法简单易懂、模块丰富、应用广泛等等。但是世界上没有有完美的东西&#xff0c;python 一个明显缺点就是运行速度慢&#xff0c;至少跟 C 语言没法比…

《5》CentOS7.0+OpenStack+kvm云平台的部署—组态Horizon

感谢朋友支持本博客&#xff0c;欢迎共同探讨交流&#xff0c;因为能力和时间有限&#xff0c;错误之处在所难免&#xff0c;欢迎指正&#xff01;假设转载。请保留作者信息。 博客地址&#xff1a;http://blog.csdn.net/qq_21398167 原博文地址&#xff1a;http://blog.csdn.n…

python怎么打开一个窗口_python – 使按钮一次只打开一个窗口(通过关闭Toplevel窗口启用按钮)...

我希望NewWinButton一次只创建一个新窗口,这意味着如果if NewWin.winfo_exists() 1:NewWinButton.config(statedisabled)else:NewWinButton.config(statenormal)如果我在新窗口中添加一个按钮(本例中为QuitButton),我可以使这个工作&#xff1a;import tkinter as tkroot tk.…

从此走上一条iOS程序猿不归路。。。

新的城市&#xff0c;新的生活&#xff01;前不久刚刚结束了苦逼的面试找工作之旅&#xff0c;期间也小有收货&#xff0c;如今正处年底工作闲暇之余&#xff0c;将前一阵子陆陆续续的总结整理了一下&#xff0c;本人菜鸟程序猿一只&#xff0c;水平有限&#xff0c;本文总结的…

springboot mysql事物_在Spring Boot中使用数据库事务

关于数据库访问还有一个核心操作那就是事务的处理了&#xff0c;前面两篇博客小伙伴们已经见识到Spring Boot带给我们的巨大便利了&#xff0c;其实不用猜&#xff0c;我们也知道Spring Boot在数据库事务处理问题上也给我们带来惊喜&#xff0c;OK&#xff0c;废话不多说&#…

什么是JSONP以及它是怎么产生的

什么是JSONP以及它是怎么产生的 1.什么是jsonp JSONP(JSON with Padding)是一个非官方的协议&#xff0c;它允许在服务器端集成Script tags返回至客户端&#xff0c;通过javascript callback的形式实现跨域访问&#xff08;这仅仅是JSONP简单的实现形式…

cinder连接mysql数据库_Openstack入门篇(十六)之Cinder服务的部署与测试

1.理解块存储服务操作系统获得存储空间的方式一般有两种&#xff1a;通过某种协议(SAS,SCSI,SAN,iSCSI 等)挂接裸硬盘&#xff0c;然后分区、格式化、创建文件系统&#xff1b;或者直接使用裸硬盘存储数据(数据库)通过 NFS、CIFS 等 协议&#xff0c;mount 远程的文件系统第一种…

Mysql经常使用命令

1.导出整个数据库 mysqldump -u username -p --default-character-setlatin1 数据库名 > 导出的文件名称(数据库默认编码是latin1) mysqldump -u wcnc -p smgp_apps_wcnc > wcnc.sql 2.导出一个表 mysqldump -u username -p 数据库名 表名> 导出的文件名称 mysqldump …

stack heap java_java中的Heap 和 Stack | 学步园

1. 栈(stack)与堆(heap)都是Java用来在Ram中存放数据的地方。与C不同&#xff0c;Java自动管理栈和堆&#xff0c;程序员不能直接地设置栈或堆。2. 栈的优势是&#xff0c;存取速度比堆要快&#xff0c;仅次于直接位于CPU中的寄存器。但缺点是&#xff0c;存在栈中的数据大小与…

JavaScript密码复杂度

<!DOCTYPE html><html><head lang"en"> <meta charset"UTF-8"> <title>密码复杂度</title></head><body><script type"text/javascript"> //密码复杂度var pwprompt("请输入密…

最后关于Pipeline完整的图如下:

最后关于Pipeline完整的图如下&#xff1a; 转载于:https://www.cnblogs.com/aaa6818162/p/5077988.html

amr 转mp3 java_JAVA 音频转换AMR 转MP3,OS,Linux cent os 7

场景近期在做微信开发时&#xff0c;需要获取用户发给公众服务号的语音留言。而从微信服务端下载来的语音格式却是amr的格式&#xff0c;同样的你手机录音、Android语音等也都是生成amr格式文件。但当你想在web页面去播放此文件时&#xff0c;就困难了。因为无论是当前HTML5的标…

input hidden用法

之前获取数据传数据&#xff0c;都是写在全局变量里&#xff0c;今天老板告诉我说用input hidden来存&#xff0c;我百度了一下&#xff0c;确实是个好方法&#xff0c;记录之&#xff1a; 1 隐藏域在页面中对于用户是不可见的&#xff0c;在表单中插入隐藏域的目的在于收集或发…