第8课 VBA输入语句InputBox

第8课 VBA输入语句InputBox
第8课 VBA输入语句InputBox

第八课输入语句Inputbox

上一节课讲述了输出语句Msgbox,它可以将某些信息输出到屏幕上。

本节课讲述与之对应的输入语句。

输入语句主要Inputbox函数和Application.Inputbox方法,它们功能相近,不过后者更强大。

第8.1节Inputbox函数

Inputbox函数是VBA中用于录入数据的函数,它可在屏幕上创建一个输入框,等待用户输入字符。当按下“确定”或者“取消”按钮后可返回用户录入的String类型的文本或者空文本(当按下“取消”键时是空文本)。

Inputbox可为用户提供数据录入窗口,然后根据用户录入的字符决定下一步的操作。

例如下图中,用户的录入信息决定程序的计算方式,这是典型的inputbox应用。

图 1 以录入值确定计算方式

8.1.1Inputbox函数的语法

Inputbox的具体语法如下:

InputBox(prompt[, title] [, default] [, xpos] [, ypos] [, helpfile, context])

其中第一参数是必选参数,其余参数为可选参数。各参数的详细解释见下表:

表 1 Inputbox的参数详解

其中最重要的是前面三个参数,包括提示信息、对话框标题和默认值。

在特殊情况下,第四、第五参数也具有其实用价值——强制指定对话框的显示位置,从

而防止对话框挡住当前窗口。

8.1.2案例应用

从以下案例中,可以加深对Inputbox的认识。

1.定制“另存为”对话框

设计一个用于文件另存的对话框,固定保存在C盘下,用户可以随意定制文件名,默认名称为当前日期。代码如下:

Sub 工作簿另存()

Dim FileName As String '声明变量

'弹出一个录入框,让用户指定文件名,默认值为当前日期

FileName = InputBox("请输入工作簿新名称", "另存为", Format(Date, "yyyy-mm-dd"), 10, 10)

'如果按下了取消或者录入空值,那么结束过程

If Len(FileName) = 0 Then Exit Sub

'当前工作簿另存到C盘中, 文件名为用户指定字符

ThisWorkbook.SaveAs "c:\" & FileName

End Sub

执行以上代码时,将弹出一个“另存为”对话框供用户录入新名称,其默认值为当前日期,如下图所示:

图 2 定制的“另存为”对话框

关于以上代码,补充八点:

(1)Inputbox的返回值总是文本,如果要求返回值不是文本尽量改用application.Inputbox。

本例中用变量FileName来保存Inputbox的值,所以变量FileName的数据类型也用String。

(2)date语句用户于获取当前的系统日期,默认的日期格式受控制面板所影响,分隔符有可能是“-”也可能是“/”,而“/”不能作为文件名称,所以本例采用Format函数将它格式化,强制使用“-”作分隔符。

(3)Format函数类似于工作表函数text,可以将数值、日期按需求转换格式。而且text函数能用的格式绝大多数都能用于Format中。

(4) InputBox函数的第4、第5参数分别使用10,表示输入框显示在屏幕左上角,离幕屏的上边缘和左边缘的距离都是10。原点是屏幕左上角,而不是Excel应用程序的左上角,当改变Excel的窗口大小可以看出差异。

(5) InputBox函数允许用户随意录入字符,也提供默认值。默认值由函数的第三参数决定。

(6)按下“取消”按钮时,函数的返回值是空文本,其长度为0。由于文件的名字不可能长度为0,所以为了防错,加入“Exit Sub”,表示用户不指定文件名称就结束过程,不再执行后面的代码。

(7) ThisWorkbook表示VBA代码所在工作簿,例如代码写在Book1中,那么ThisWorkbook 代表Book1,代码写在Book2中那么ThisWorkbook代表Book2。

(8) Workbook.SaveAs方法表示将工作簿另存,可以使用关键字“Workbook.SaveAs方法”在帮助中搜索到它的详细说明。它的参数是文件路径,查例采用的“"c:\" & FileName”。

2.根据指定月份批量创建工作表

要求:用户指定一个月份,程序创建以该月每日日期命名的工作表。代码如下:Sub 新建工作表() '批量建立新表,个数等于本月天数,同时对日期命名,并建立目录

Dim i As Byte, months As Byte '声明变量

'弹出一个对话框,让用户指定月份,默认显示当前月

months = InputBox("请输入月份,程序将建立该月每日日期命名的工作表", "确定月份", Month(Date))

'批量生成工作表,其个数等于指定月份的天数减去当前已有工作表个数,即确保工作表数量等于该月天数

WorkSheets.Add After:=WorkSheets(WorkSheets.Count), Count:=Day(DateSerial(Year(Date), months + 1, 0)) - Sheets.Count

'将所有工作表重命名,工作表名对应每日的日期

For i = 1 To Worksheets.Count

WorkSheets(i).Name = months & "月" & i & "日" '对每个工作表命名

Next i

MsgBox "建立完毕!", 64

End Sub

执行以上代码时,先弹出以下对话框:

图 3 输入月份(默认值是当前月的月份)

录入月份后可以得到以下结果:

图 4 以指定月中每日日期命名的工作表

针对以上代码需要补充五点:

(1)代码中“Dim i As Byte, months As Byte”用于声明变量和变量的数据类型,这是下一节课的讲述重点。本课时稍有了解即可。

数据类型Byte的范围是0-255,因为月份和日期的范围是1-12和1-31,所以宜用Byte 型变量。

(2) Month函数用于计算日期值的月份。由于Date表示当前系统日期,所以Month(Date)的计算结果是本月月份。

(3)由于要创建等于整月天数的工作表,而工作簿中已经在若干个工作表,可能1个也可能3个,所以本例采用的办法是整月的天数减去现有的工作表数量(WorkSheets.Count)。

Worksheets.Add方法表示创建工作表,其语法如下:

Worksheets.Add(Before, After, Count, Type)

其中Before和After表示新表的参照位置,两者只能取其一。

Count参数表示工作表的数量,即一次性创建的数量。本例采用的是“Day(DateSerial(Year(Date), months + 1, 0)) - Worksheets.Count”,即整月天数减去已经有的工作表数量。

Type参数表示新表的类型,默认值是工作表。

(4)代码“After:=Worksheets(Worksheets.Count)”表示新表的位置是最后一个工作表之后。“Worksheets.Count”表示工作表的总数量,“Worksheets(Worksheets.Count)”则是最后一个工作表。

(5)“Day(DateSerial(Year(Date), months + 1, 0))”比较难懂一点。“DateSerial(Year(Date), months + 1, 0)”表示变量months所代表的月份的下一个月的0号这一天的日期值,由于日期函数DateSerial可以智能地调节日期,没有0日这一天,所以将下月0日调整为本月最后一天。代码正是利用了这个智能调节功能,故意将月份设置为months + 1,将日期设置为0日,从而简单地获得months月最后一天的日期。

最后利用Day函数计算这个日期在当月中属于第几天。例如2013年2月28日的日期序号是41333,Day函数能将它转换成28,表示这一天是当月的第28天。

(6)创建好工作表后,利用一个循环语句对工作表重命名,

“For i = 1 To Worksheets.Count”表示从第1表到最后一个工作表。

“Worksheets(i).Name = months & "月" & i & "日"”表示对工作表逐个命名为“X月Y日”格式的工作表名称。

在第21课时会讲到循环语句。

(7)如果在Inputbox中需要更多的提示信息,那么可以使用Chr(10)来分行。例如本例中Inputbox语句可以修改为:

months = InputBox("请输入月份,程序将建立该月每日日期命名的工作表" & Chr(10) & "例如输入4月,则产生的工作表则为4月1日、4月2日……", "确定月份", Month(Date))

3.将A1日期按指定样式转换为星期

A1存放日期,现需将其转换为星期,程序需要让用户决定转换方式,即提供三个可选项。

达成以上需求可以使用代码:

Sub 将A1日期转换为星期()

Dim Week As Byte '声明变量

'提供输入框,让用户选择转换方式。在输入框中可以预览转换后的结果

Week = InputBox("请选择转换样式:" & Chr(10) & "输入1:" & WorksheetFunction.Text ([a1], "DDD") & Chr(10) _

& "输入2:" & WorksheetFunction.Text ([a1], "DDDD") & Chr(10) & "输入3:" & WorksheetFunction.Text ([a1], "AAA") & Chr(10) _

& "输入4:" & WorksheetFunction.Text ([a1], "AAAA"), "选择转换样式", 1)

'根据用户录入的数字对A1的日期进行转换

[b1] = WorksheetFunction.Text ([a1], Choose(Week, "DDD", "DDDD", "AAA", "AAAA")) End Sub

该过程中利用Inputbox显示一个输入框,在输入框中可以预览转换后的四种日期样式,只要输入1到4之间的任何数字,程序会对应地转换日期为星期格式。

假设A1是2013-3-2,那么输入框外观如下图所示。

图5提示用户选择转换样式

在该过程中,使用了Choose函数,它可以根据第一参数的值从后面的参数中选择对应的值作为Text程序没有使用防错功能,如果输入的值小于1或者大于4将产生错误。

第8.2节Inputbox的限制

前面展示了Inputbox函数的功能及其在实际应用中的神奇功效,但也不代表它没有缺陷。它不仅有缺陷,而且有较多缺陷。要更好地发挥程序的功能、更好地运用好字符输入框,就有必要了解它到底有哪些限制。

整体而言,Inputbox函数主要有以下限制,制约着它无法更好地在VBA中展现其功能:

1.不能检验用户录入字符的数据类型

通常,在VBA中期望终端用户录入什么类型的数据,但有时终端用户基于测试或者其他目的,会故意录入错误的数据,此时程序可能会弹出与实际错误不相符的提示。而作为开发者,有必要防范此事故发生。

例如录入表示月份的数值时,要求用户输入1到12的数字,但用户如果故意输入“5月”或者“五”,那么程序会产生错误,而且对于此类错误,Inputbox并没有内置任何防范措施。

2.不能产生单元格引用

如果用户需要输入单元格地址,在Inputbox对话框中,用户只能手工录入地址。这显然效率不高且容易产生错误。例如在Excel 2010使用兼容模式下却手工输入了“ZZ100”之类的错误。而更理想的方式是让用户直接选择区域,程序自动将选区地址返回给对话框。

这种问题只能留给Application对象的Inputbox方法来处理。

3.字符长度限制

对话框中的字符串和用户录入的字符(即第一和第三参数)都限定1024左右,如果是纯汉字则为511个。

如果用户的需求超过以上限制,应该考虑使用窗体来体现。

第8.3节Application.InputBox 方法

VBA中有一个与Inputbox函数功能类似,却强大很多的语句——Application.Inputbox方法。

要注意它是方法,不是函数。

Application.Inputbox方法在功能上与Inputbox函数基本一致,但却提供了数据类型检测

和直接产生区域引用的功能,大大方便了用户的使用。

在工作中尽量使用Application.Inputbox方法替代Inputbox函数。

使用时一定要注意,不对用户录入信息进行验证的是VBA中的Inputbox函数,带验证功能的是Application.Inputbox方法。

8.3.1Application.Inputbox语法详解

Application.Inputbox方法的基本语法如下:

Application.InputBox(Prompt, Title, Default, Left, Top, HelpFile, HelpContextID, Type)

表2中包括了Application.Inputbox方法的各参数详解。

表 2 Application.Inputbox方法的各参数详解

Application.Inputbox方法有8个参数,其中最重要的是前三个和最后一个。Type参数可以指定一种或者多种数据类型,而Application.Inputbox方法则会根据类型对用户的录入信息进行检查,如果不符合指定类型则会阻止程序执行。

8.3.2案例应用

现对Type参数在工作中的应用展示三个案例。

1.强制用户录入数值

以图6中提示用户录入月份为例,强制用户录入1到12月的数值,否则程序拒绝执行。Application.Inputbox方法完全可以胜任,代码如下:

Sub 数值校验()

months = Application.InputBox("请指定月份", "月份", Month(Date), 10, 10, , , 1)

MsgBox months

End Sub

其中最后一个参数1表示只能录入数值。

当用户执行代码时,如果在对话框中录入非数值“5月”,那么程序将提示“无效的数字”,如下图所示:

图 6 录入非数值时的提示

2.对任意选区进行行列合计

假设要对一个区域进行横向、纵向求和,通过Application.InputBox方法来选择区域会比直接在代码中指定区域灵活得多。

案例代码如下:

Sub 行列自动合计()

Dim rng As Range, address As String '声明一个对象变量

'如果当前选择的对象是单元格则将单元格地址赋予变量,否则将空文本赋予变量

IF TypeName(Selection) = "Range" Then address = Selection.address Else address = ""

'弹出一个对话框, 让用户选择区域, 默认显示变量address的值。然后将该用户选择区域赋予变量rng

Set rng = Application.InputBox("请选择待合计的区域", "合计区域", address, , , , , 8)

IF rng Is Nothing Then Exit Sub

'先汇总各行的值

For i = 1 To rng.Rows.Count '从1到总行数

'利用Offset取得汇总数据的放置位置, 即选区第一个单元格向右偏移选区的列数

'合计区域也用Offset逐行偏移来获取, Resize的作用是重置为1行, 否则会汇总其他行的数据

rng(1).Offset(i - 1, rng.Columns.Count) = WorksheetFunction.Sum (rng.Offset(i -

1).Resize(1))

Next

'再汇总各列的值

For i = 1 To rng.Columns.Count + 1 '从1到总列数加1,因为需要对行的汇总数再进行汇总

rng(1).Offset(rng.Rows.Count, i - 1) = WorksheetFunction.Sum (rng.Offset(, i -

1).Resize(, 1))

Next

End Sub

在本过程中Application.InputBox语句默认显示的是当前选区地址,可以手动选择区域,从而重新产生地址在输入框中。然后过程根据用户选择的区域进行横向、纵向合计。

Application.Inputbox方法的Type参数使用8,表示返回单元格引用,其数据类型为Range。

图7 通过鼠标拖动录入区域地址

下图是计算结果:

图8 计算结果

很显然,Application.InputBox方法除了检校功能外,自由选择区域的功能相当人性化。

3.利用Application.Inputbox录入公式

在单元格中录入公式时,Excel会对公式进行检查,如果不符合公式的基本语法会阻止用户录入。而VBA中的Inputbox方法也可以实现同等功能。

例如对下图的数据进行排名次:

图9 成绩表

如果使用VBA的对话框来录入公式,那么代码如下:

Sub 设置计算名次的公式()

'首先选择待输入公式的单元格

[c2].Select

'设置C2的公式, 第8参数必须用零, 否则单元格中显示值而非公式

[c2].FormulaLocal = Application.InputBox("请输入计算名次的公式:", "公式", , , , , , 0)

'填充公式

Range("C2").AutoFill Destination:=Range("C2:C" & Cells(Rows.Count, 2).End(xlUp).Row) End Sub

该过程中,Application.Inputbox第八个参数使用零,表示在C2单元格产生公式,如果使用其他值作为参数则只能产生公式的结果,而非公式本身。

利用Application.InputBox方法录入公式时需要注意四点:

(1)在弹出对话框前必须先定位于目标单元格,否则公式中引用的单元格或者区域会产生错位,类似于条件格式中的引用;

(2)在对话框中录入公式时,可以利用鼠标单击单元格来产生地址,而且可以通过快捷键【F4】使其在相对引用、绝对引用与混合引用三个状态之间切换,与直接在单元格中录入公式的方式一致;

(3)在代码中必须对存放公式的单元格使用FormulaLocal属性,那么VBA就会对录入的公式进行检测,如果录入的字符不符合公式的格式,那么将阻止程序继续执行,从而确保公式的正确性;

(4)如果需要在单元格中录入数组公式,则需要使用FormulaArray 属性。代码如下:

[c2].FormulaArray = Application.InputBox("请输入计算名次的公式:", "公式", , , , , , 0) 执行本过程时,VBA会弹出一个输入公式的对话框,在其中录入公式“=rank(B2,$B$2:$B$8)”,如下图所示,然后单元格C2会自动产生公式,且将公式向下填充,直到B列最后一个非空单元格。

图10在对话框录入排名次的公式

如果在其中录入一个不完整的公式“=rank(B2,$B$2:$B$8”,那么VBA会提示用户公式缺少括号,如下图所示:

图11 公式缺少括号时弹出提示框

如果用户在对话框中录入公式时忽略了等号,那么VBA会将它当作文本字符串,自动添

加引号及等号。例如用户录入“rank(B2,$B$2:$B$8)”,那么单元格中则会产生以下公式:="rank(B2,$B$2:$B$8)"

Application.Inputbox方法录入的公式可以在看不见的工作表中执行,这是相对手工录入公式的优越性。例如,sheet2属于隐藏状态,那么以下语句完全不影响正常执行,仍然可以在目标单元格产生正确公式:

Sheet2.[c2].FormulaLocal = Application.InputBox("请输入计算名次的公式:", "公式", , , , , , 0)

由于今天时间比较紧,没法及时给大家出课后练习题,明天我会补上,放在以下网址:https://www.360docs.net/doc/9c1990382.html,/forum-39-1.html

明天我会在群里公布作业内容和具体的帖子地址,请在家踊跃参与。

学习的目的是应用,不是将知识放在硬盘中。所以以后的每堂课的课后作业请大家及时参与,不要怕答案不完善,或者可能出错。

没有错过的人很难进步的。

相关主题
相关文档
最新文档