Excel VBA Userform-搜索和更新现有行

时间:2018-11-20 01:18:40

标签: excel vba excel-vba userform

我有一个非常适合将新数据输入电子表格的用户窗体。我想对此进行修改,以使“更新”按钮将数据保存到同一行而不进行重复。我还想使“搜索”在A1行的工作表中已有某种类型的值的下拉列表。我仍在学习VBA,我的代码可能一团糟,而且我不知道从哪里开始。这是一项正在进行的工作-任何帮助,建议,想法等,我们将不胜感激!

当前用户表单:

Private Sub CloseForm_Click()
'Close UserForm.
    Unload Me
End Sub

Private Sub EnterOutage_Click()
Sheets("Outages and Switching").Select
Range("A1").Select
Do Until ActiveCell.value = ""
ActiveCell.Offset(0, 0).Select
Loop
ActiveCell.Offset(1, 1).value = Me.REQ_Rev1.value
ActiveCell.Offset(1, 2).value = Me.SOS_Rev1.value
ActiveCell.Offset(1, 3).value = Me.OutageStart1.value
ActiveCell.Offset(1, 4).value = Me.OutageEnd1.value
ActiveCell.Offset(1, 5).value = Me.ConstRel.value
ActiveCell.Offset(1, 6).value = Me.Dispatch1.value
ActiveCell.Offset(1, 7).value = Me.OutageType1.value
ActiveCell.Offset(1, 8).value = Me.BPID1.value
ActiveCell.Offset(1, 9).value = Me.WorkOrder1.value
ActiveCell.Offset(1, 10).value = Me.Station_Line1.value
ActiveCell.Offset(1, 11).value = Me.Description.value
ActiveCell.Offset(1, 12).value = Me.Remarks1.value
ActiveCell.Offset(1, 13).value = Me.REQ_Link1.value
ActiveCell.Offset(1, 14).value = Me.SOS_Link1.value

End With
End Sub

Private Sub Image1_Click()
MyVal = "datFirstDay"
UserForm1.Show
End Sub

Private Sub CommandButton1_Click()

End Sub

Private Sub CommandButton2_Click()

End Sub

Private Sub CommandButton3_Click()

End Sub

Private Sub NewOutage_Click()

End Sub

Private Sub OutageEnd1_Enter()
OutageEnd1 = CalendarForm.GetDate
End Sub

Private Sub OutageStart1_Enter()
OutageStart1 = CalendarForm.GetDate
End Sub

Private Sub SaveOutage_Click()
'Changes start date to mm/dd/yyyy
 Dim dDate As Date
    'Sheet2.Range("D1").Value = dDate
Dim ws As Worksheet
    Dim addme As Long
    Set ws = Worksheets("Outages and Switching")
    addme = ws.Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Row
' Creates userform text input boxes
    With ws
        ws.Cells(addme, 1).value = Me.REQ_Rev1.value 'the number 1 here represents the Column A
        ws.Cells(addme, 2).value = Me.SOS_Rev1.value 'the number 2 here represents the Column B
        ws.Cells(addme, 7).value = Me.OutageStart1.value 'the number 7 represents Column G
        ws.Cells(addme, 8).value = Me.OutageEnd1.value 'the number 8 represents Column H
        ws.Cells(addme, 11).value = IIf(Me.ConstRel.value, 1, -1) 'the number 11 represents Column K, checkbox sends number instead of True/False
        ws.Cells(addme, 13).value = Me.Dispatch1.value 'the number 13 represents Column M
        ws.Cells(addme, 14).value = Me.OutageType1.value 'the number 14 represents Column N
        ws.Cells(addme, 15).value = Me.BPID1.value 'the number 15 represents Column O
        ws.Cells(addme, 16).value = Me.WorkOrder1.value 'the number 16 represents Column P
        ws.Cells(addme, 17).value = Me.Station_Line1.value 'the number 17 represents Column Q
        ws.Cells(addme, 22).value = Me.Description1.value 'the number 22 represents Column V
        ws.Cells(addme, 23).value = Me.Remarks1.value 'the number 23 represents Column W
        ws.Cells(addme, 24).value = Me.REQ_Link1.value 'the number 24 represents Column X
        ws.Cells(addme, 25).value = Me.SOS_Link1.value 'the number 25 represents Column O
    End With

'Reset text boxes code
'https://www.ozgrid.com/forum/forum/help-forums/excel-general/103251-how-to-clear-all-textboxes-and-checkbox-in-a-userform

        Dim oneControl As Object

For Each oneControl In OutageData.Controls
    Select Case TypeName(oneControl)
        Case "TextBox"
            oneControl.Text = vbNullString
        Case "CheckBox"
            oneControl.value = False
    End Select
Next oneControl


End Sub

Private Sub SearchOutage_Click()
Dim rng As Range
Dim i As Long
Dim lst As Range

If Me.REQ_Rev1.value = "" Then
MsgBox "Please enter a REQ number to find!", vbExclamation
Me.REQ_Rev1.SetFocus
Exit Sub
End If
With Sheets("Outages and Switching")
Set rng = .Range("A:A")
Set rng = rng.Find(What:=Me.REQ_Rev1.value, After:=.Range("A14"), LookAt:=xlWhole)
If rng Is Nothing Then
MsgBox "REQ not found!", vbExclamation
Me.REQ_Rev1.SetFocus
Exit Sub
End If

        Me.REQ_Rev1.value = rng.Offset(0, 0).value  'the number 0 here represents the Column A
        Me.SOS_Rev1.value = rng.Offset(0, 1).value  'the number 1 here represents the Column B
        Me.OutageStart1.value = rng.Offset(0, 6).value 'the number 6 represents Column G
        Me.OutageEnd1.value = rng.Offset(0, 7).value  'the number 7 represents Column H
        'IIf(Me.ConstRel.value, 1, -1) = rng.Offset(0, 11).value  'the number 11 represents Column K, checkbox sends number instead of True/False
        Me.Dispatch1.value = rng.Offset(0, 12).value  'the number 12 represents Column M
        Me.OutageType1.value = rng.Offset(0, 13).value  'the number 13 represents Column N
        Me.BPID1.value = rng.Offset(0, 14).value  'the number 14 represents Column O
        Me.WorkOrder1.value = rng.Offset(0, 15).value  'the number 15 represents Column P
        Me.Station_Line1.value = rng.Offset(0, 16).value  'the number 16 represents Column Q
        Me.Description1.value = rng.Offset(0, 23).value  'the number 23 represents Column V
        Me.Remarks1.value = rng.Offset(0, 24).value  'the number 24 represents Column W
        Me.REQ_Link1.value = rng.Offset(0, 25).value  'the number 25 represents Column X
        Me.SOS_Link1.value = rng.Offset(0, 26).value  'the number 26 represents Column O

End With
End Sub

Private Sub UpdateOutage_Click()

End Sub

' Forces user to use "Close" button instead of "X"
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
    Cancel = True
    MsgBox "Please use the Close Form button"
  End If
End Sub

我根据雷蒙德的回复修改了我的代码。它更接近功能,现在将数据复制回工作表。现在,我还有一个用户窗体,可以在工作表中添加一个新的“中断”行,而另一个用户表则用于“更新”。

以下是“更新”的当前流程:

  1. 用户打开“更新”用户窗体,然后在“ REQ1”组合框中输入REQ#

  2. 用户单击“搜索”。这将搜索工作表,并在用户表单中填充相应的数据

  3. 用户对字段进行更改,然后选择“更新”

  4. 用户窗体中的值会重新加载到工作表中。

这是修改后的代码:

Private Sub UserForm_Initialize()

' Disables all text fields except REQ# on UserForm Load
With Me
        .REQ_Rev1.Enabled = False
        .SOS1.Enabled = False
        .SOS_Rev1.Enabled = False
        .OutageStart1.Enabled = False
        .OutageEnd1.Enabled = False
        .ConstRel.Enabled = False
        .Dispatch1.Enabled = False
        .OutageType1.Enabled = False
        .BPID1.Enabled = False
        .WorkOrder1.Enabled = False
        .Station_Line1.Enabled = False
        .Device_Section1.Enabled = False
        .Description1.Enabled = False
        .Remarks1.Enabled = False
        .REQ_Link1.Enabled = False
        .SOS_Link1.Enabled = False
        .UpdateOutage1.Enabled = False
    End With


' >> Populate and sort ComboBox 1(REQ#) with data from 'Outages and Switching' sheet, column 1 <<
' https://www.tek-tips.com/viewthread.cfm?qid=1747506

Dim myRange As Range

    Set myRange = Sheets("Outages and Switching").Range("A15:A80")
    With Sheets("Outages and Switching").Sort
        .SortFields.Clear
        .SortFields.Add myRange, xlSortOnValues, xlAscending
        .SetRange myRange
        .Apply
    End With

    Me.REQ1.List = myRange.value

' >> Populate ComboBox 1(Dispatch) with data from 'Master List' sheet, column 1 <<

 ' Assign Variables

Dim Cl As Range

    With CreateObject("scripting.dictionary")
        For Each Cl In Sheets("Master List").ListObjects("Table2").ListColumns(1).DataBodyRange
            If Not .Exists(Cl.value) Then .Add Cl.value, Nothing
        Next Cl
         Dispatch1.Clear
         Dispatch1.List = Application.Transpose(.keys)
         .RemoveAll
    End With

' >> Populate ComboBox 2(Outage Type) with data from 'Master List' sheet, column 2 <<
    With CreateObject("scripting.dictionary")
        For Each Cl In Sheets("Master List").ListObjects("Table2").ListColumns(2).DataBodyRange
            If Not .Exists(Cl.value) Then .Add Cl.value, Nothing
        Next Cl
         OutageType1.Clear
         OutageType1.List = Application.Transpose(.keys)
         .RemoveAll
    End With
End Sub

Private Sub Image1_Click()
MyVal = "datFirstDay"
UserForm1.Show
End Sub

Private Sub Search1_Click()
Dim rng As Range
Dim i As Long
Dim lst As Range

If Me.REQ1.value = "" Then
        MsgBox "Please enter an REQ number to find!", vbExclamation
        Me.REQ1.SetFocus
    Exit Sub
End If

With Sheets("Outages and Switching")
    Set rng = .Range("A:A")
    Set rng = rng.Find(What:=Me.REQ1.value, After:=.Range("A14"), LookAt:=xlWhole)
        If rng Is Nothing Then
            MsgBox "REQ not found!", vbExclamation
        Me.REQ1.SetFocus
    Exit Sub
End If
' Imports Outage values into UserForm based on REQ# search
        Me.REQ1.value = rng.Offset(0, 0).value  'the number 0 here represents the Column A
        Me.REQ_Rev1.value = rng.Offset(0, 1).value  'the number 0 here represents the Column A
        Me.SOS1.value = rng.Offset(0, 2).value  'the number 1 here represents the Column B
        Me.SOS_Rev1.value = rng.Offset(0, 3).value  'the number 1 here represents the Column B
        Me.OutageStart1.value = rng.Offset(0, 8).value 'the number 6 represents Column G
        Me.OutageEnd1.value = rng.Offset(0, 9).value  'the number 7 represents Column H
        'Me.ConstRel.value(1, -1) = rng.Offset(0, 13).value  'the number 11 represents Column K, checkbox sends number instead of True/False
        Me.Dispatch1.value = rng.Offset(0, 14).value  'the number 12 represents Column M
        Me.OutageType1.value = rng.Offset(0, 15).value  'the number 13 represents Column N
        Me.BPID1.value = rng.Offset(0, 16).value  'the number 14 represents Column O
        Me.WorkOrder1.value = rng.Offset(0, 17).value  'the number 15 represents Column P
        Me.Station_Line1.value = rng.Offset(0, 18).value  'the number 16 represents Column Q
        Me.Device_Section1.value = rng.Offset(0, 19).value  'the number 17 represents Column R
        Me.Description1.value = rng.Offset(0, 25).value  'the number 23 represents Column V
        Me.Remarks1.value = rng.Offset(0, 26).value  'the number 24 represents Column W
        Me.REQ_Link1.value = rng.Offset(0, 27).value  'the number 25 represents Column X
        Me.SOS_Link1.value = rng.Offset(0, 28).value  'the number 26 represents Column O

End With

With Me 'Enables text boxes after search is performed
        .REQ_Rev1.Enabled = .REQ1.value <> vbNullString
        .SOS1.Enabled = .REQ1.value <> vbNullString
        .SOS_Rev1.Enabled = .REQ1.value <> vbNullString
        .OutageStart1.Enabled = .REQ1.value <> vbNullString
        .OutageEnd1.Enabled = .REQ1.value <> vbNullString
        .ConstRel.Enabled = .REQ1.value <> vbNullString
        .Dispatch1.Enabled = .REQ1.value <> vbNullString
        .OutageType1.Enabled = .REQ1.value <> vbNullString
        .BPID1.Enabled = .REQ1.value <> vbNullString
        .WorkOrder1.Enabled = .REQ1.value <> vbNullString
        .Station_Line1.Enabled = .REQ1.value <> vbNullString
        .Device_Section1.Enabled = .REQ1.value <> vbNullString
        .Description1.Enabled = .REQ1.value <> vbNullString
        .Remarks1.Enabled = .REQ1.value <> vbNullString
        .REQ_Link1.Enabled = .REQ1.value <> vbNullString
        .SOS_Link1.Enabled = .REQ1.value <> vbNullString
        .UpdateOutage1.Enabled = .REQ1.value <> vbNullString
    End With

End Sub

Private Sub UpdateOutage1_Click()
Dim rng As Range
Dim i As Long
Dim lst As Range

With Sheets("Outages and Switching")
    Set rng = .Range("A:A")
    Set rng = rng.Find(What:=Me.REQ1.value, After:=.Range("A14"), LookAt:=xlWhole)
        If rng Is Nothing Then
            MsgBox "REQ not found!", vbExclamation
        Me.REQ1.SetFocus
    Exit Sub
End If

        rng.Offset(0, 0).value = Me.REQ1.value  'the number 0 here represents the Column A
        rng.Offset(0, 1).value = Me.REQ_Rev1.value  'the number 0 here represents the Column A
        rng.Offset(0, 2).value = Me.SOS1.value  'the number 1 here represents the Column B
        rng.Offset(0, 3).value = Me.SOS_Rev1.value  'the number 1 here represents the Column B
        rng.Offset(0, 6).value = Me.OutageStart1.value 'the number 6 represents Column G
        rng.Offset(0, 7).value = Me.OutageEnd1.value  'the number 7 represents Column H
        'rng.Offset(0, 11).value = Me.ConstRel.value(1, -1) 'the number 11 represents Column K, checkbox sends number instead of True/False
        rng.Offset(0, 12).value = Me.Dispatch1.value  'the number 12 represents Column M
        rng.Offset(0, 13).value = Me.OutageType1.value  'the number 13 represents Column N
        rng.Offset(0, 14).value = Me.BPID1.value  'the number 14 represents Column O
        rng.Offset(0, 15).value = Me.WorkOrder1.value 'the number 15 represents Column P
        rng.Offset(0, 16).value = Me.Station_Line1.value 'the number 16 represents Column Q
        rng.Offset(0, 17).value = Me.Device_Section1.value 'the number 17 represents Column R
        rng.Offset(0, 23).value = Me.Description1.value 'the number 23 represents Column V
        rng.Offset(0, 24).value = Me.Remarks1.value 'the number 24 represents Column W
        rng.Offset(0, 25).value = Me.REQ_Link1.value 'the number 25 represents Column X
        rng.Offset(0, 26).value = Me.SOS_Link1.value  'the number 26 represents Column O'

End With
End Sub

Private Sub OutageEnd1_Enter()
OutageEnd1 = CalendarForm.GetDate
End Sub

Private Sub OutageStart1_Enter()
OutageStart1 = CalendarForm.GetDate
End Sub



Private Sub CloseForm_Click()
'Close UserForm.
    Unload Me
End Sub

' Forces user to use "Close" button instead of "X"
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = vbFormControlMenu Then
    Cancel = True
    MsgBox "Please use the Close Form button"
  End If

End Sub

这是用户表单的屏幕截图:

Update Outage UserForm

我现在正在努力解决一件事:

  1. 如何将“ ConstRel”复选框的状态加载到用户表单中,并在更新后将其复制回工作表?它是当前被注释掉的值,因为我似乎无法弄清楚语法。如果我未包括“ 1”和“ -1”,则它在工作表上显示为TRUE / FALSE,而不是YES / NO。到目前为止,我已经尝试了以下各种方法,但均未成功:

    (Me.ConstRel.value,1,-1)= rng.Offset(0,10)

再次感谢您的协助和耐心,因为我在VBA中迷路了!

1 个答案:

答案 0 :(得分:1)

希望此代码对您有所帮助。尝试反转代码。

Cells(TextBox1.Text, 2).Value = TextBox2.Text

要更新

TextBox2.Text = Cells(TextBox1.Text, 2).Value