简体   繁体   English

Excel VBA获取完整的文本框值

[英]Excel VBA get complete textbox value

I am new to VBA. 我是VBA的新手。 I have a textbox that is being populated by bar code scanner using Excel. 我有一个文本框,条形码扫描仪使用Excel填充该文本框。 There are different values on the form, for example: 表单上有不同的值,例如:

608001F
608001
001IN

I need to check if the code contains 'F' and then do a certain action, otherwise do another action. 我需要检查代码是否包含“ F”,然后执行某些操作,否则执行其他操作。 I do this on Textbox_Change() function, which is causing the 608001 code to be triggered first. 我在Textbox_Change()函数上执行此操作,这导致先触发608001代码。 How can I make it trigger the code with the 'F' in it first? 如何使它首先触发带有“ F”的代码?

My code looks like this (edited for brevity, so excuse if any syntax errors): 我的代码如下所示(为简洁起见,因此编辑,如果出现语法错误,请原谅):

Private Sub TextBox1_Change()
Value = TextBox1.Value
If Value <> "" Then
    If (Len(Value) = 7 And Right(Value, 1) = "F") Then
        ActiveCell.Value = Value
        ActiveSheet.Cells(ActiveCell.Row + 1, 1).Select
        TextBox1.Value = ""
        TextBox1.Activate
    ElseIf (Len(Value) = 6 Or (Len(Value) = 5 And (Right(Value, 2) = "IN" Or Right(Value, 2) = "EM"))) Then
        ActiveCell.Value = Value
        Selection.Offset(0, 1).Select
        TextBox1.Value = ""
        TextBox1.Activate
    Else
        'Do nothing
    End If
End Sub

EDIT 编辑

I decided to clarify what is happening better. 我决定澄清正在发生的事情。 When using the _Change() function, the condition when I reach character 6 is fulfilled first, meaning the the code is seen as 608001 instead of 608001F as should be the case. 使用_Change()函数时,首先要满足我到达字符6的条件,这意味着该代码被视为608001而不是608001F。

After clarifying with OP, the problem is this: 用OP弄清楚之后,问题是这样的:

  • The string is not typed by the user manually, but by a code scanner which "works as a person" typing letter by letter; 该字符串不是由用户手动键入的,而是由代码扫描器(“作为一个人工作”)逐个字母键入的;
  • The inserted string might trigger a wrong part of the code without being still finished. 插入的字符串可能会触发代码的错误部分,而尚未完成。

A possible solution coming to my mind is a timer which is waiting for the code scanner to write the code into the box, then running the code. 我想到的一个可能的解决方案是一个计时器 ,它正在等待代码扫描器将代码写入框中,然后运行代码。 Basically: 基本上:

Declare a global variable 声明一个全局变量

... to remember if the countdown has started yet or not. ...记住倒计时是否已经开始。

Dim started As Boolean

Write your code into another macro 将您的代码写入另一个宏

... add the standard code to a macro which is not related to a Change event: ...将标准代码添加到与Change事件无关的宏中:

Private Sub TextBox1_Change_Personal() '<-- not triggered if TextBox1 is changed!
Value = TextBox1.Value
If Value <> "" Then
    If (Len(Value) = 7 And Right(Value, 1) = "F") Then
        ActiveCell.Value = Value
        ActiveSheet.Cells(ActiveCell.Row + 1, 1).Select
        TextBox1.Value = ""
        TextBox1.Activate
    ElseIf (Len(Value) = 6 Or (Len(Value) = 5 And (Right(Value, 2) = "IN" Or Right(Value, 2) = "EM"))) Then
        ActiveCell.Value = Value
        Selection.Offset(0, 1).Select
        TextBox1.Value = ""
        TextBox1.Activate
    Else
        'Do nothing
    End If
    started = False '<-- reset control variable for next code
End Sub

Activate the macro after 3 seconds 3秒后激活宏

... when the code scanner will start writing into the textbox, you "activate a countdown" (basically, you schedule your personal macro to start in 3 seconds). ...当代码扫描程序将开始写入文本框时,您“激活了倒数计时”(基本上,您将您的个人宏计划在3秒内启动)。 So, before the 3 seconds run, the code scanner will have finished to write the code and you don't fall into the same mistake. 因此,在运行3秒钟之前,代码扫描器将完成编写代码的工作,您不会遇到相同的错误。

Private Sub TextBox1_Change()
    If started = False Then
        Application.OnTime TimeSerial(Hour(Now()), Minute(Now()),Second(Now())+3), "TextBox1_Change_Personal"
        started = True '<-- deactivating control variable to avoid re-scheduling each time
    End If
End Sub

Of course, the 3 seconds are a mock value; 当然,这3 seconds是一个模拟值; your code scanner might be much faster in writing the value into the box (in that case, decrease to 1 second for example) or slower (in that case, increase to 5 seconds for example). 您的代码扫描程序将值写入框中的速度可能会快得多(例如,减少到1秒),或者慢一些(例如,增加到5秒)。

Final (should work) code 最终(应工作)代码

Dim started As Boolean
Private Sub TextBox1_Change()
    If started = False Then
        Application.OnTime TimeSerial(Hour(Now()), Minute(Now()),Second(Now())+3), "TextBox1_Change_Personal"
        started = True '<-- deactivating control variable to avoid re-scheduling each time
    End If
End Sub
Private Sub TextBox1_Change_Personal() '<-- not triggered if TextBox1 is changed!
    Value = TextBox1.Value
    If Value <> "" Then
        If (Len(Value) = 7 And Right(Value, 1) = "F") Then
            ActiveCell.Value = Value
            ActiveSheet.Cells(ActiveCell.Row + 1, 1).Select
            TextBox1.Value = ""
            TextBox1.Activate
        ElseIf (Len(Value) = 6 Or (Len(Value) = 5 And (Right(Value, 2) = "IN" Or Right(Value, 2) = "EM"))) Then
            ActiveCell.Value = Value
            Selection.Offset(0, 1).Select
            TextBox1.Value = ""
            TextBox1.Activate
        Else
            'Do nothing
        End If
        started = False '<-- reset control variable for next code
    End Sub

You can use the InStr() function to find if a character exists in the string, the function returns 0 if the character doesn't exist. 您可以使用InStr()函数查找字符串中是否存在字符,如果字符不存在,则函数返回0。 Then simply check if the return value is greater than 0. 然后只需检查返回值是否大于0。

This simple example should give you a clue. 这个简单的例子应该为您提供线索。

Sub lookForF()

    Dim inVal As String

    inVal = Range("A4").Value

    If InStr(1, inVal, "F") > 0 Then

        'Your code here when F exists
    Else

        'Your code here for other case

    End If

End Sub

Is it so that the string below is all in the same, single textbox? 是否使下面的字符串全部在同一个文本框中?

608001F
608001
001IN

If so, use the SPLIT() function, passing in vbcrlf in order to get an array of each barcode, each line of text & loop through them. 如果是这样,请使用SPLIT()函数,传入vbcrlf以获得每个条形码的数组,每行文本并遍历它们。

If you're meaning the textbox only holds one of those codes at a time and 608001 replaces 608001F, then use a private variable in order to store the previous textbox value. 如果您的意思是文本框一次仅包含其中一个代码,而608001替换了608001F,则使用私有变量以存储先前的文本框值。

Private m_earlierBarcodeVal As String

Private Sub UserForm_Initialize()
    m_earlierBarcodeVal = TextBox1.Text
End Sub

Private Sub TextBox1_Change()
    MsgBox "Old value= " & m_earlierBarcodeVal & vbCrLf & _
    "New value= " & TextBox1.Text

    m_earlierBarcodeVal = TextBox1.Text
End Sub

Something like this perhaps then? 大概是这样吗? EDITED after better understanding the problem (see reply comments below): 在更好地理解问题后进行了编辑(请参见下面的回复评论):

Private m_previousBarcodeString As String
Private m_isFirstBarcodeEntered As Boolean

Private Sub UserForm_Initialize()
    m_isFirstBarcodeEntered = True

    ' Some test data only. You don't need to use the rest of this
    ' method code below as you have a barcode scanner.
    Dim barcodesArray(2) As String
    barcodesArray(0) = "608001F"
    barcodesArray(1) = "608001"
    barcodesArray(2) = "001IN"

    Dim barcodeIndex As Integer
    Dim barcodeCount As Long
    Dim charIndex As Integer
    Dim charCount As Integer
    barcodeCount = UBound(barcodesArray)

    For barcodeIndex = 0 To barcodeCount
        charCount = Len(barcodesArray(barcodeIndex))

        For charIndex = 1 To charCount
            TextBox1.Text = TextBox1.Text & Mid(barcodesArray(barcodeIndex), charIndex, 1)
        Next charIndex

        TextBox1.Text = ""
    Next barcodeIndex
End Sub

Private Sub TextBox1_Change()
    If (m_isFirstBarcodeEntered = True) Then
        m_isFirstBarcodeEntered = False
    Else
        If Len(TextBox1.Text) = 0 Then
            MsgBox "Was '" & m_previousBarcodeString & "' ending in 'F'?: " & _
            UCase(isValidBarcode(m_previousBarcodeString))
        Else
            m_previousBarcodeString = TextBox1.Text
        End If
    End If
End Sub

Private Function isValidBarcode(ByVal singleBarcodesString As String) As Boolean
    isValidBarcode = False

    If Len(singleBarcodesString) = 7 Then
        If UCase(Right(singleBarcodesString, 1)) = "F" Then
            isValidBarcode = True
        End If
    End If
End Function

If I understood your problem, it seems you don't want the Change event to be triggered until you don't give some sort of confirmation to say "I finished inserting the value" . 如果我理解了您的问题,似乎您不希望触发Change事件,直到您不给出某种确认说“我已完成插入值”

In that case, what I might suggest is to write the code using a " " separator (ie until you don't press SpaceBar to confirm the successful insertion, nothing happens). 在这种情况下,我建议使用" "分隔符编写代码(即,直到不按SpaceBar确认成功插入为止,什么都不会发生)。 In order to reach this, all you need is adding two new lines of code (see edit below): 为了达到这个目的,您需要添加两行新代码(请参见下面的编辑):

Private Sub TextBox1_Change()
Value = TextBox1.Value
If Value <> "" Then
If Right(Value,1) = " " Then '<-- new line
    If (Len(Value) = 7 And Right(Value, 1) = "F") Then
        ActiveCell.Value = Value
        ActiveSheet.Cells(ActiveCell.Row + 1, 1).Select
        TextBox1.Value = ""
        TextBox1.Activate
    ElseIf (Len(Value) = 6 Or (Len(Value) = 5 And (Right(Value, 2) = "IN" Or Right(Value, 2) = "EM"))) Then
        ActiveCell.Value = Value
        Selection.Offset(0, 1).Select
        TextBox1.Value = ""
        TextBox1.Activate
    Else
        'Do nothing
    End If
 End If '<-- new line
 End If
End Sub

Like that, your code will work like this: 这样,您的代码将像这样工作:

1) You write 608001 ... 1)您写608001 ...

Before: The Len() = 6 condition was triggered so you didn't have the time to eventually type the F in; 之前:触发了Len() = 6条件,因此您没有时间最终键入F

Now: waiting for user confirmation 现在:等待用户确认

2) You write 608001F ... 2)您写608001F ...

Before: The Len() = 7 would have been triggered, but you didn't have the time to type the last char F ; 之前: Len() = 7会被触发,但是您没有时间键入最后一个字符F

Now: waiting for user confirmation 现在:等待用户确认

3) Press SpaceBar --> the code starts running and you will not confuse the 6 char string with the 7 char string any longer. 3)按SpaceBar ->代码开始运行,您将不再将6 char字符串与7 char字符串混淆。 Please note that pressing the SpaceBar means "I'm submitting my barcode". 请注意,按SpaceBar表示“我正在提交条形码”。 Which means, you can replace the SpaceBar character with any other of the Chr() collection ( Enter , a number, a letter etc.). 这意味着,您可以用任何其他Chr()集合( Enter ,数字,字母等)替换SpaceBar字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM