首页 > 其他分享 >VBA一例:如何保持文本框焦点

VBA一例:如何保持文本框焦点

时间:2023-04-15 21:16:29浏览次数:44  
标签:VBA Sub 一例 KeyDown 窗体 文本框 ByVal 焦点

  • 缘起

在Excel的VBA编程中,设计一个用于录入的用户窗体,该窗体包含1个文本框和2个按钮,文本框用于扫描枪的录入。

要求扫描枪可以连续录入,即每扫描完一个条码,文本框自动清空,文本框继续获得焦点。

 

我们知道扫描枪录入实际上等同于往文本框录入一段字符串并回车, 那么刚才的要求理论上可以在文本框的KeyDown事件子过程中编程,先判断录入的字符是否回车键,如果是则清空文本框。

1 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
2     If KeyCode = 13 Then TextBox1.Value = ""
3 End Sub

至此,如果是VB编程,要求本应完成。但实际运行发现,扫描枪录入后,文本框虽然自动清空,但是焦点却跑到下一个按钮上去了。

 

  • 求因

未及细想,手动用SetFocuse方法来设置文本框获得焦点。

1 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
2     If KeyCode = 13 Then 
3         TextBox1.Value = ""
4         TextBox1.SetFocus
5     End If
6 End Sub

程序再运行,焦点还是跑到按钮上。不解,遂跟踪之,发现是在执行完KeyDown事件子过程后(End Sub语句后)发生的焦点转移,难怪SetFocus方法显得没有起作用。

为什么执行完KeyDown事件后会发生焦点自动转移呢?百思不得其解,遂清除代码反复测试,终于搞清楚一个结论:在Excel VBA编程中,文本框控件接收到回车键以后,会将焦点移到Tab键顺序的下一个对象。(这一结论通过参阅文本框控件的EnterKeyBehavior属性说明也可侧面印证)

之所以特别强调是在Excel VBA编程中,是因为我依稀仿佛记得在VB6里面,系统是不会“聪明的”帮文本框做焦点转移的。(多年不用VB6了,回忆的事情未必正确!但是,其它许多面向事件的UI编程里面,系统是不会自动帮忙文本框做焦点转移的。)

 

  • 证果

既然查明原委,自然应找寻解决之道,且看我折腾。从文本框按下回车键到Button1按钮获得焦点,依次产生如下事件:

复制代码 1 TextBox1_KeyDown( ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As fmShiftState)

3 TextBox1_Exit( ByVal Cancel As MSForms.ReturnBoolean)

5 Button1_Enter( )

7 Button1_KeyPress( ByVal KeyANSI As MSForms.ReturnInteger)

9 Button1_KeyUp( ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As fmShiftState) 复制代码

我的初步想法既然焦点转移是不可干预的系统行为,那就“事后”将它逆转回来,如此从Exit事件开始往后都可以用SetFocus方法将焦点重新设回文本框(此处说法不严谨,如果在Exit事件里面实现,不适用SetFocus方法,而是用Cancel=True,个中原因请自查VBA帮助)。但这样带来一个逻辑问题,从业务上判断,只有在文本框输入操作时,才需要让文本框保持焦点,其它时候不需要,否则会导致除了文本框之外的其它控件都得不到焦点,无法操作!因此干预焦点转移的代码逻辑只能在KeyDown事件中实现。

既然不能“事后”逆转,那就只能从中打断了。我又尝试了在KeyDown事件中用 Exit Sub 或 Call 跳出子过程,未果,系统仍然会自动做焦点转移。

灵光乍现间,我想到既然不能打断子过程,何不打断事件。方法是再做一个UserForm2窗体,当在文本框按回车时,隐藏现有窗体,显示

UserForm2窗体,这时会触发UserForm2的Activate事件, 同时窗体显示的切换也打断了文本框向按钮转移焦点,那么只要在Activate事件中再隐藏UserForm2窗体,显示原窗体,设置焦点到文本框就OK了。这个事件是在KeyDown事件子过程中通过代码人为产生的,是受控的,因此可以将其看作是KeyDown事件代码逻辑的一部分。

复制代码 1 'UserForm1窗体

3 Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
4     If KeyCode = 13 Then
5         TextBox1.Value = ""
6         UserForm1.Hide
7         UserForm2.Show
8     End If
9 End Sub 复制代码

 

复制代码 1 'UserForm2窗体

3 Private Sub UserForm_Activate()
4     UserForm2.Hide
5     UserForm1.Show
6     UserForm1.TextBox1.SetFocus
7 End Sub 复制代码

实测效果非常理想,窗体切换的速度肉眼根本察觉不到,感觉就是文本框保持焦点,用条码枪连续输入,不需要键盘和鼠标辅助定位。

标签:VBA,Sub,一例,KeyDown,窗体,文本框,ByVal,焦点
From: https://www.cnblogs.com/KL58/p/17321850.html

相关文章

  • [vba]-Excel-VBA操作文件四大方法之四(转)
     四、利用API函数来处理文件通过前面三种方法的介绍,你是否已经觉得足够了?是的,前面的方法完全可以应付几乎所有的文件操作。但是为了普及一下API,展示一下API的魅力,最后向大家介绍一下如何利用API函数来处理文件。另一方面也是本人对API情有独钟,为她做一下广告,呵呵。大家......
  • [vba]-Excel-VBA操作文件四大方法之三(转)
    三、利用FileSystemObject对象来处理文件FileSystemObject对象模型,是微软提供的专门用来访问计算机文件系统的,具有大量的属性、方法和事件。其使用面向对象的“object.method”语法来处理文件夹和文件,使用起来十分方便(需Office2000以后版本)。FileSystemObject并不是VBA的一部......
  • [vba]-Excel-VBA操作文件四大方法之二(转)
    二、利用VBA文件处理语句来处理文件   VBA包含了许多用于文件操作的语句和函数,可以满足绝大多数情况下的文件操作要求。下面我们按照操作目的进行一一介绍。(一)文件处理   1.Name语句语法:NameoldpathnameAsnewpathname功能:重命名一个文件、目录、或文件夹,移动一......
  • [vba]-Excel-VBA操作文件四大方法之一(转)
    在我们日常使用Excel的时候,不仅会用到当前Excel文件的数据,还经常需要访问其他的数据文件。这些数据文件可能是Excel文件、文本文件或数据库文件等。经常有朋友会问如何在vba代码里操作这些数据文件?本文就系统地介绍一下在Excel中应用VBA操作数据文件的方法。本文主要介绍四种常......
  • VBA
     几种从数据库读取数据生成excel文件的比较OFFICE精英俱乐部『VBA交流』我的自学收集资料以下是近段时间从不同地方收集到的一些学习资料,希望对新手有借鉴作用,同时感谢各位对我的支持和帮助,先发60小点,代码可能不完全正确,请指正.全部显示1,Application.CommandBars("W......
  • EXCEL VBA编程的一些小结
     最近单位内部的项目里要用到些报表EXCEL的生成,虽说JAVA的POI可以有这能力,但觉得还是可能比较麻烦,因此还是转用.net来搞,用visualstudio2003配合office2003,用到了一些VBA,因此小结并归纳之,选了些资料归纳在这里,以备今后查考首先创建 Excel 对象,使用ComObj:DimExcelIDas......
  • Excel VBA语句集
    (第1辑)定制模块行为(1)OptionExplicit'强制对模块内所有变量进行声明OptionPrivateModule'标记模块为私有,仅对同一工程中其它模块有用,在宏对话框中不显示OptionCompareText'字符串不区分大小写OptionBase1'指定数组的第一个下标为1(2)OnErrorResumeNext'忽略......
  • 基于VBA的Excel抽奖软件
    Problem一个抽奖软件,效果图如下。点击随机数或者按钮3会进行抽奖。Solution1、Excel打开开发者工具2、插入按钮,选择指定宏3、编写VBA程序4、另存为启用宏的xlsmCodesSubASD_Click()DimaAsIntegerRandomizea=Int(Rnd()*59+1)Range("a14")=aEndSubSubASDF_Clic......
  • vba-事务
    SubaccTrans()DimConnAsNewADODB.Connection'Conn.Open".......连接你的Acc数据库.........."OnErrorGoToErrHndl:Conn.BeginTrans'事务开始Sql="updateasetnum=1000whereid=24"'第一个sql语句......
  • VBA 对象数组排序算法分享
     FunctionSrotObjectByProperty(objsToSortAsVariant,PropertyNameAsString,Optional降序AsBoolean=True)IfIsEmpty(objsToSort)ThenExitFunctionIfInStr(TypeName(objsToSort),"()")<1ThenExitFunction'IsArray()issom......