第一章电子表格专业函数编程1.1如何把“度.分秒”角度变成弧度?在Excel中,自带了大量的商务、办公标准函数,唯独没有把“度.分秒”角度变成“弧度”和将“弧度”转换为“度.分秒”或“°′″”这样的专业计算函数。在测绘、工程、科学计算中,这经常是一个无法回避的问题。怎么办?打开Excel,选择“工具”→“宏”→“VisualBasic编辑器”→“帮助”→“VisualBasic语言参考”→“语句”→“A-L”→“Function”,就可以详细看到编写函数“Function”的相关语法:[Public|Private|Friend][Static]Functionname[(arglist)][Astype][statements][name=expression][ExitFunction][statements][name=expression]EndFunctionFunction语句的语法包含下面部分:部分描述Public可选的。表示所有模块的所有其它过程都可访问这个Function过程。如果是在包含OptionPrivate的模块中使用,则这个过程在该工程外是不可使用的。Private可选的。表示只有包含其声明的模块的其它过程可以访问该Function过程。Friend可选的。只能在类模块中使用。表示该Function过程在整个工程中都是可见的,但对于对象实例的控制者是不可见的。Static可选的。表示在调用之间将保留Function过程的局部变量值。Static属性对在该Function外声明的变量不会产生影响,即使过程中也使用了这些变量。name必需的。Function的名称;遵循标准的变量命名约定。arglist可选的。代表在调用时要传递给Function过程的参数变量列表。多个变量应用逗号隔开。type可选的。Function过程的返回值的数据类型,可以是Byte、Boolean、Integer、Long、Currency、Single、Double、Decimal(目前尚不支持)、Date、String(除定长)、Object、Variant或任何用户定义类型。statements可选的。在Function过程中执行的任何语句组。expression可选的。Function的返回值。其中的arglist参数的语法以及语法各个部分如下:[Optional][ByVal|ByRef][ParamArray]varname[()][Astype][=defaultvalue]部分描述Optional可选的。表示参数不是必需的。如果使用了该选项,则arglist中的后续参数都必须是可选的,而且必须都使用Optional关键字声明。如果使用了ParamArray,则任何参数都不能使用Optional声明。ByVal可选的。表示该参数按值传递。ByRef可选的。表示该参数按地址传递。ByRef是VisualBasic的缺省选项。ParamArray可选的。只用于arglist的最后一个参数,指明最后这个参数是一个Variant元素的Optional数组。使用ParamArray关键字可以提供任意数目的参数。ParamArray关键字不能与ByVal,ByRef,或Optional一起使用。varname必需的。代表参数的变量的名称;遵循标准的变量命名约定。type可选的。传递给该过程的参数的数据类型;可以是Byte、Boolean、Integer、Long、Currency、Single、Double、Decimal(目前尚不支持)、Date、String(只支持变长)、Object或Variant。如果参数不是Optional,则也可以是用户定义类型,或对象类型。defaultvalue可选的。任何常数或常数表达式。只对于Optional参数时是合法的。如果类型为Object,则显式缺省值只能是Nothing。说明如果没有使用Public、Private或Friend显式指定,则Function过程缺省为公用。如果没有使用Static,则局部变量的值在调用之后不会保留。Friend关键字只能在类模块中使用。但Friend过程可以被工程的任何模块中的过程访问。Friend过程不会在其父类的类型库中出现,且Friend过程不能被后期绑定。小心Function过程可以是递归的;也就是说,该过程可以调用自己来完成某个特定的任务。不过,递归可能会导致堆栈上溢。通常Static关键字和递归的Function过程不在一起使用。所有的可执行代码都必须属于某个过程。不能在另外的Function、Sub或Property过程中定义Function过程。ExitFunction语句使执行立即从一个Function过程中退出。程序接着从调用该Function过程的语句之后的语句执行。在Function过程的任何位置都可以有ExitFunction语句。Function过程与Sub过程的相似之处是:Function过程是一个可以获取参数,执行一系列语句,以及改变其参数值的独立过程,而与子过程不同的是:当要使用该函数的返回值时,可以在表达式的右边使用Function过程,这与内部函数,诸如Sqr、Cos或Chr的使用方式一样。在表达式中,可以通过使用函数名,并在其后用圆括号给出相应的参数列表来调用一个Function过程。请参阅Call语句关于如何调用Function过程的详细说明。要从函数返回一个值,只需将该值赋给函数名。在过程的任意位置都可以出现这种赋值。如果没有对name赋值,则过程将返回一个缺省值:数值函数返回0,字符串函数返回一个零长度字符串(),Variant函数则返回Empty。如果在返回对象引用的Function过程中没有将对象引用赋给name(通过Set),则函数返回Nothing。下面的示例说明如何给一个名为BinarySearch的函数赋返回值。在这个示例中,将False赋给了该函数名,表示没有找到某个值。FunctionBinarySearch(...)AsBoolean...'值未找到,返回一个False值。IflowerupperThenBinarySearch=FalseExitFunctionEndIf...EndFunction在Function过程中使用的变量分为两类:一类是在过程内显式声明的,另一类则不是。在过程内显式声明的变量(使用Dim或等效方法)都是局部变量。对于那些没有在过程中显式声明的变量,除非它们在该过程外更高级别的位置有显示地声明,否则也是局部的。小心过程可以使用没有在过程内显式声明的变量,但只要有任何在模块级别中定义的名称与之相同,就会产生名称冲突。如果过程中使用的未声明的变量与另一个过程,常数,或变量的名称相同,则会认为过程使用的是模块级的名称。显式声明变量就可以避免这类冲突。可以使用OptionExplicit语句来强制显式声明变量。小心VisualBasic可能会重新安排数学表达式以提高内部效率。若Function过程会改变某个数学表达式中变量的值,则应避免在此表达式中使用该函数。Function语句示例该示例使用Function语句来声明Function过程的名称、参数、以及构成Function过程主体的代码。最后一个例子中使用了确定类型的、初始化的Optional参数。'下面的用户自定义函数返回'它的参数的平方根。FunctionCalculateSquareRoot(NumberArgAsDouble)AsDoubleIfNumberArg0Then'评估参数。ExitFunction'退出调用过程。ElseCalculateSquareRoot=Sqr(NumberArg)'返回平方根。EndIfEndFunction使用ParamArray关键字可以使函数接收数目可变的参数。在下面的定义中,FirstArg是按值传递的。FunctionCalcSum(ByValFirstArgAsInteger,ParamArrayOtherArgs())DimReturnValue'如果用如下代码调用该函数:ReturnValue=CalcSum(4,3,2,1)'则局部变量被赋予以下值:FirstArg=4,'OtherArgs(1)=3,OtherArgs(2)=2,等等。'假设缺省数组下界=1。Optional参数可以带缺省值,可以是除Variant之外的任何类型。'如果函数的参数定义如下:FunctionMyFunc(MyStrAsString,OptionalMyArg1As_Integer=5,OptionalMyArg2=Dolly)DimRetVal'则可用如下代码调用该函数:RetVal=MyFunc(Hello,2,World)'提供了所有3个参数。RetVal=MyFunc(Test,,5)'省略了参数2。'参数1和参数3使用了命名的参数。RetVal=MyFunc(MyStr:=Hello,MyArg1:=7)********************************************************************请认真反复学习和理解Function语句的语法和示例。我们的任务是编制自己的专业函数去完成特定的专业计算任务。编制把“度.分秒”角度变成弧度的函数自然是公用的,用于进行通用三角函数的计算,用Public(公用的)声明;参数通过关键字ByVal(通过值)声明,选择按值传递,是因为按值传递,改变过程内部的参数时将不会影响到原来的变量,所以,我们的专业计算函数的编程的一般格式应为:PublicFunctionRad(ByValangleAsDouble)AsDoubleDimAAsDouble,BAsDouble,CAsDouble,DAsDoubleDimangAsDouble,signAsIntegerang=Abs(angle)+0.0000000000001:sign=Sgn(angle)A=Int(ang):B=(ang-A)*100#:C=Int(B):D=(B-C)*100#Rad=sign*(A+C/60#+D/3600#)*M_RADEndFunction说明:第1行:表示定义函数名为弧度Rad;参数angle按值传递,数据类型为双精度Double,函数的返回值的数据类型也是Double;第2~6行:函数的语句体,其中:第2~3行:用Dim语句,声明函数过程变量A,B,C,D,ang的数据类型为双精度型Double,sign为整型Integer;第4~5行:“度.分秒”的角度值angle变换成十进制的度,其中调用了系统函数取绝对值Abs(x),取±Sgn(x),取整数Int(x);第6行:函数弧度Rad返回值;其中M_RAD是一常数,可用定义常数语句进行定义:PublicConstM_SEC#=206264.8'1弧度=206264.8″PublicConstM_DEG#=57.2957795130823'1弧度=57.2957795130823°PublicConstM_RAD#=1.74532925199433E-02'1度=1.74532925199433E-02弧度PublicConstM_PI#=3.14159265358979'π=3.14159265358979第7行:函数结束语句。接下来,就是进行模块代码输入、调试了:打开Excel的VB编辑器,选择“插入”→模块,在模块代码编辑窗口中输入:PublicConstM_SEC#=206264.8'1弧度=206264.8″PublicConstM_DEG#=57.2957795130823'1弧度=57.2957795130823°PublicConstM_RAD#=1.74532925199433E-02'1度=1.74532925199433E-02弧度PublicConstM_PI#=3.14159265358979'π=3.