综合实例

为了巩固本章所学,安排了3个与函数有关的示例,给出了Excel VBA和Python两个版本的代码。

函数示例1-计算圆环的面积

图10-2所示工作表中第3列和第4列为各圆环的外半径和内半径数据,现利用数据计算各圆环的面积。计算圆环面积的公式为:S=pi*(R*R-r*r),其中,pi为圆周率,R和r为圆环的外半径和内半径,计算公式返回圆环面积S。

Document Image

图10-2 计算圆环的面积

计算各圆环的面积之前,先将计算面积的公式写成函数,这样对每个圆环进行计算时,可以重复调用该函数计算面积。

【Excel VBA】

示例文件的存放路径为Samples\ch10\Excel VBA\计算圆环的面积.xlsm。

code.vba
Function CircleArea(dblR1 As Double, dblR2 As Double) As Double
  '计算圆环的面积
  'dblR1为外半径,dblR2为内半径
  CircleArea = 3.1416 * (dblR1 * dblR1 - dblR2 * dblR2)
End Function
Sub Test()
  Dim intI As Integer
  Dim intR As Integer  '数据最大行号
  Dim intL As Integer, intU As Integer
  Dim dblR1(), dblR2(), dblArea()  '外半径,内半径,面积
  Dim sht As Object
  Set sht = ActiveSheet
  intR = sht.Range("C2").End(xlDown).Row
  '获取数据,转换为一维数组
  dblR1 = sht.Range("C3:C" & CStr(intR)).Value
  dblR1 = Application.WorksheetFunction.Transpose(dblR1)
  dblR2 = sht.Range("D3:D" & CStr(intR)).Value
  dblR2 = Application.WorksheetFunction.Transpose(dblR2)
  intL = LBound(dblR1)
  intU = UBound(dblR1)
  ReDim dblArea(intL To intU)

  '调用函数计算各圆环面积
  For intI = intL To intU
    dblArea(intI) = CircleArea(CDbl(dblR1(intI)), CDbl(dblR2(intI)))
  Next

  '输出
  sht.Range("E3").Resize(intU - intL + 1, 1).Value = _
               Application.WorksheetFunction.Transpose(dblArea)
End Sub

运行程序,在工作表中E列输出各圆环的面积。

【Python】

本示例的数据文件存放路径为Samples\ch10\Python\计算圆环的面积.xlsx,py文件保存在相同目录下,文件名为sam10-01.py。

code.python
def circle_area(r1,r2):
    #计算圆环的面积
    #r1为外半径,r2为内半径
    return 3.1416*(r1*r1-r2*r2)
import xlwings as xw  #导入xlwings包
#从constants类中导入Direction
from xlwings.constants import Direction
import os  #导入os包
#获取本py文件的当前路径
root = os.getcwd()
#创建Excel应用,可见,没有工作簿
app=xw.App(visible=True, add_book=False)
#打开数据文件,可写
bk=app.books.open(fullname=root+\
    r'\计算圆环的面积.xlsx',read_only=False)
sht=bk.sheets(1)  #获取第1个工作表
#工作表中第3列数据最大行号
row_num=sht.api.Range('C2').End(Direction.xlDown).Row
areas=[]
#调用函数计算各圆环的面积,结果添加到列表中
for i in range(row_num-2):
    areas.append(circle_area(sht.cells(i+3,3).value,sht.cells(i+3,4).value))
#输出结果
sht.range('E3').options(transpose=True).value=areas

运行脚本,在工作表中E列输出各圆环的面积。

函数示例2-递归计算阶乘

图10-3所示工作表中第3列给出了整数1到10,现在希望计算它们各自对应的阶乘,输出在第4列。

Document Image

图10-3 计算给定整数的阶乘

计算之前,需要构造一个计算指定整数阶乘的函数。整数n的阶乘n!可以看作n与n-1的阶乘的乘积,即n*(n-1)!,而n-1的阶乘又可以看作n-1与n-2的阶乘的乘积,即(n-1)*(n-2)!,如此可以用递归算法进行计算。

【Excel VBA】

首先构造递归函数Factorial,然后遍历C列每个整数,调用该函数计算阶乘。示例文件的存放路径为Samples\ch10\Excel VBA\递归计算阶乘.xlsm。

code.vba
Function Factorial(lngN As Long) As Long
  '用递归求lngN的阶乘
  If lngN > 1 And lngN <= 20 Then
    Factorial = lngN * Factorial(lngN - 1)
  Else
    Factorial = 1
  End If
End Function
Sub Test()
  Dim intI As Integer
  Dim intR As Integer  '数据最大行号
  Dim intL As Integer, intU As Integer
  Dim lngN(), lngV()  '给定的数字及其阶乘
  Dim sht As Object
  Set sht = ActiveSheet
  intR = sht.Range("C2").End(xlDown).Row
  '获取数据,转换为一维数组
  lngN = sht.Range("C2:C" & CStr(intR)).Value
  lngN = Application.WorksheetFunction.Transpose(lngN)
  intL = LBound(lngN)
  intU = UBound(lngN)
  ReDim lngV(intL To intU)

  '调用函数求阶乘
  For intI = intL To intU
    lngV(intI) = Factorial(CLng(lngN(intI)))
  Next

  '输出
  sht.Range("D2").Resize(intU - intL + 1, 1).Value = _
               Application.WorksheetFunction.Transpose(lngV)
End Sub

运行程序,在工作表D列输出各整数的阶乘。

【Python】

首先构造递归函数factorial,然后遍历C列每个整数,调用该函数计算阶乘。本示例的数据文件存放路径为Samples\ch10\Python\递归计算阶乘.xlsx,py文件保存在相同目录下,文件名为sam10-02.py。

code.python
def factorial(n):
    #计算整数n的阶乘
    if n==1:return 1
    return n*factorial(n-1)
import xlwings as xw  #导入xlwings包
#从constants类中导入Direction
from xlwings.constants import Direction
import os  #导入os包
#获取本py文件的当前路径
root = os.getcwd()
#创建Excel应用,可见,没有工作簿
app=xw.App(visible=True, add_book=False)
#打开数据文件,可写
bk=app.books.open(fullname=root+\
    r'\递归计算阶乘.xlsx',read_only=False)
sht=bk.sheets(1)  #获取第1个工作表
#工作表中第3列数据最大行号
row_num=sht.api.Range('C2').End(Direction.xlDown).Row
lst=[]
#调用函数计算各整数的阶乘,结果添加到列表中
for i in range(row_num-1):
    lst.append(factorial(sht.cells(i+2,3).value))
#输出结果
sht.range('D2').options(transpose=True).value=lst

运行脚本,在工作表D列输出各整数的阶乘。

函数示例3-删除字符串中的数字

图10-4所示工作表中第3列给出了一些由字母和数字组成的字符串,现在希望删除这些字符串中的数字。

Document Image

图10-4 删除字符串中的数字

处理这些字符串之前,先构造一个删除字符串中数字的函数。数字的ASCII码为48-57,遍历字符串中的每个字符,获取当前字符的ASCII码,如果它落在48-57的范围内,就去掉它,否则保留。

【Excel VBA】

首先构造去除字符串中数字的函数DelNumers,然后遍历C列每个字符串,重复调用DelNumers函数进行处理。Excel VBA中用Asc函数获取字符的ASCII码。示例文件的存放路径为Samples\ch10\Excel VBA\删除字符串中的数字.xlsm。

code.vba
Function DelNumers(strOri As String)
  Dim strChar As String
  Dim strTemp As String
  Dim intI As Integer
  strTemp = ""
  '变量字符串中的每个字符
  For intI = 1 To Len(strOri)
    strChar = Mid(strOri, intI, 1)
    '数字的ASCII码48-57
    '如果不在这个范围内,添加字符;否则忽略
    If Asc(strChar) < 48 Or Asc(strChar) > 57 Then
      strTemp = strTemp & strChar
    End If
  Next
  DelNumers = strTemp
End Function
Sub Test()
  Dim intI As Integer
  Dim intR As Integer
  Dim intL As Integer, intU As Integer
  Dim strV(), strR()
  Dim sht As Object
  Set sht = ActiveSheet
  intR = sht.Range("C2").End(xlDown).Row
  '获取数据,转换为一维数组
  strV = sht.Range("C3:C" & CStr(intR)).Value
  strV = Application.WorksheetFunction.Transpose(strV)
  intL = LBound(strV)
  intU = UBound(strV)
  ReDim strR(intL To intU)
  '调用函数去除数字
  For intI = intL To intU
    strR(intI) = DelNumers(CStr(strV(intI)))
  Next

  '输出
  sht.Range("D3").Resize(intU - intL + 1, 1).Value = _
                  Application.WorksheetFunction.Transpose(strR)
End Sub

运行程序,在工作表D列输出去除数字后的字符串。

【Python】

首先构造去除字符串中数字的函数del_numbers,然后遍历C列每个字符串,重复调用del_numbers函数进行处理。Python中用ord函数获取字符的ASCII码。本示例的数据文件存放路径为Samples\ch10\Python\删除字符串中的数字.xlsx,py文件保存在相同目录下,文件名为sam10-03.py。

code.python
def del_numbers(st):
    #从给定字符串中去除数字
    st0=''
    #遍历字符串中的每个字符
    for i in range(len(st)):
        #数字的ASCII码48-57
        #如果不在这个范围内,添加字符;否则忽略
        if ord(st[i])<48 or ord(st[i])>57:
            st0=st0+st[i]
    return st0

import xlwings as xw  #导入xlwings包
#从constants类中导入Direction
from xlwings.constants import Direction
import os  #导入os包
#获取本py文件的当前路径
root = os.getcwd()
#创建Excel应用,可见,没有工作簿
app=xw.App(visible=True, add_book=False)
#打开数据文件,可写
bk=app.books.open(fullname=root+\
    r'\删除字符串中的数字.xlsx',read_only=False)
sht=bk.sheets(1)  #获取第1个工作表
#工作表中第3列数据最大行号
row_num=sht.api.Range('C3').End(Direction.xlDown).Row
lst=[]
#调用函数计算各整数的阶乘,结果添加到列表中
for i in range(row_num-2):
    lst.append(del_numbers(sht.cells(i+3,3).value))
#输出结果
sht.range('D3').options(transpose=True).value=lst

运行脚本,在工作表D列输出去除数字后的字符串。