I have a userform that I need to get users to enter multiple sets of tasks, as well as an estimate of the time that it will take to undertake each task.
After each task, and time estimate, I would like for the information to be entered on a spreadsheet, and the fields become blank again, for the next task to be entered.
This is the main code:
Global i As Integer ' Rows
Global j As Integer ' Columns
Global tCount As Integer ' Task Count
Sub Time_Calcs()
Dim mcHours As Integer ' M/C process in hours
Dim hDays As Integer ' Hours available per day
i = 2
j = 3
tCount = 1
hDays = 6
Worksheets("Calculations").Activate
Cells.Delete
i = i + 1
Cells(i, 2) = "Item"
Cells(i, 3) = "Task"
Cells(i, 4) = "# of iterations"
Cells(i, 5) = "Maker"
Cells(i, 6) = "Checker"
i = i + 1
TaskForm.Show
End Sub
I have 2 questions:
1) How can I get the code to loop through a series of instructions, such as taking the information from the form, and putting it into a spreadsheet, before clearing the data for the next task to be entered? I've tried this code, but it only seems to work for one iteration.
Private Sub CommandButton1_Click()
j = 3
Cells(i, 2) = tCount
While j <= 6
If j = 3 Then
Cells(i, j) = TaskName
ElseIf j = 4 Then
Cells(i, j) = NoofIts
ElseIf j = 5 Then
Cells(i, j) = mTime
ElseIf j = 6 Then
Cells(i, j) = cTime
End If
j = j + 1
Wend
i = i + 1
j = 3
tCount = tCount + 1
'MSForms.Control(TaskName).Value = vbNullString
'MSForms.Control(NoofIts).Value = vbnullstrins
'MSForms.Control(mTime).Value = vbNullString
'MSForms.Control(cTime).Value = vbNullString
TaskName = vbNullString
NoofIts = vbNullString
mTime = vbNullString
cTime = vbNullString
End Sub
2) After I enter data, I would like the user to be able to TAB to the next box. Currently, if I hit TAB, it TABs the cursor right. How do I get it to enable moving to the next box/button via the TAB button?
You should have a couple of procedures to add the data to the worksheet and to clear the form of existing data.
Clearing the form is just a case of going through each control on the form and settings it's value to some default - usually Null.
Private Sub Reset()
Dim ctrl As Control
For Each ctrl In Me.Controls
Select Case TypeName(ctrl)
Case "TextBox", "ComboBox"
ctrl.Value = Null
Case "OptionButton"
ctrl.Value = False
Case Else
'Do nothing
End Select
Next ctrl
End Sub
Saving the form data can be quite complicated depending on the checks you want to make before allowing the data to be transferred.
I make use of the Tag property of a control to store the column number is should be saved in and the data type of the data.
So something like 16;CCur would indicate it will be saved in column 16 as currency.
The actual code to save the data would start with finding the last cell on the worksheet containing data - this can then be used to place the new data on the next available row.
Each control is then checked and the data saved to the column indicated by in the tag property.
After all the data has been saved the form is reset and the initialize routine executed
Private Sub btnSave_Click()
Dim rLastCell As Range
Dim ctrl As Control
Dim lCol As Long
Dim wrkSht As Worksheet
Set wrkSht = ThisWorkbook.Worksheets("Raw Data")
Set rLastCell = wrkSht.Cells(wrkSht.Rows.Count, 1).End(xlUp).Offset(1)
For Each ctrl In Me.Controls
With ctrl
If TypeName(ctrl) = "TextBox" Or TypeName(ctrl) = "ComboBox" Then
If Trim(ctrl.Value) <> "" Then
If InStr(.Tag, ";") > 0 Then
lCol = Split(.Tag, ";")(0)
'Decide which data type to use.
Select Case Split(.Tag, ";")(1)
Case "CLNG"
wrkSht.Cells(rLastCell.Row, CLng(lCol)) = CLng(ctrl.Value)
Case "CCur"
wrkSht.Cells(rLastCell.Row, CLng(lCol)) = CCur(ctrl.Value)
Case "CDATE"
wrkSht.Cells(rLastCell.Row, CLng(lCol)) = CDate(ctrl.Value)
Case "CSTR", "CSENTENCE"
wrkSht.Cells(rLastCell.Row, CLng(lCol)) = CStr(ctrl.Value)
Case "CDBL"
wrkSht.Cells(rLastCell.Row, CLng(lCol)) = CDbl(ctrl.Value)
Case "CPER"
wrkSht.Cells(rLastCell.Row, CLng(lCol)) = CDbl(ctrl.Value) / 100
wrkSht.Cells(rLastCell.Row, CLng(lCol)).NumberFormat = "0.00%"
Case Else
End Select
End If
End If
End If
End With
Next ctrl
Reset
UserForm_Initialize
End Sub
I've added the UserForm_Initlialize procedure as it sets up the form for data entry - todays date is entered in a control, combo-boxes are set up, a label is given a caption showing the current Value Added Tax amount from a named range and the correct control is given focus:
Private Sub UserForm_Initialize()
Me.TextBox1 = Format(Date, "dd-mmm-yyyy")
Me.lblVAT = "VAT # " & Format$(ThisWorkbook.Names("VAT").RefersToRange, "Percent")
With Me.ComboBox1
.AddItem "A"
.AddItem "B"
.AddItem "C"
End With
Me.TextBox1.SetFocus
End Sub
I have extensions to the code - code that automatically converts names to propercase, doesn't allow more than 2 decimal places or only allows whole numbers. There's also code to check that required data has been entered and highlight the controls which are missing data before saving to the sheet. That would take a whole lot more to explain though.
Related
I have developed an userform, with two Listbox multiple option.
I have populated the listbox1 with "locations" eg:Germany, USA, UK ; from sheet list.
I have populated listbox2, with the "locations"eg:Germany, USA, UK from sheet list_Man.
My objective is to filter the rows in my sheet "result", depending upon the locations selection. The location are available in column L and M of my sheet "result"
I have an function Do filter for this.
Sub DoFilter()
Dim Ws As Worksheet
Dim strCriteria() As String
Dim arrIdx As Integer
Dim xRow As Integer
arrIdx = 0
For xRow = 2 To Last(1, List.Cells)
If List.Cells(xRow, 2) = True Then
ReDim Preserve strCriteria(0 To arrIdx)
strCriteria(arrIdx) = List.Cells(xRow, 3)
arrIdx = arrIdx + 1
End If
Next xRow
Set Ws = ThisWorkbook.Sheets("Result")
If arrIdx = 0 Then
Ws.UsedRange.AutoFilter
Else
Ws.Range("A:R").AutoFilter Field:=12, Criteria1:=Array(strCriteria), Operator:=xlFilterValues
End If
End Sub
![this is the user form that have been designed. The Listbox1 has the locations from the list sheet and the listbox2 has the locations from the List_Man sheet.
The filter option, according to the selection in the listbox, filters the column L and M of the sheet "Result". exit buton, unloads and returns to the original sheet clearing the filter option.]1
Now the userform works in such a way that, if I select both the listbox, then I get the option filtered.
I would like to have an code in my command button, in such a way that
[![If I am selecting more than one option in listbox1,"USA and UK" and in listbox2, I am selecting "Germany", then I need the filtered rows in result sheet for these option".
also the case in viceversa should be possible. If I select only location2 in listbox2, I should be able to see the filtered rows in the sheet"result".
if I am selecting more than one option in listbox2, and one option in listbox1, then I should be able to see the result accordingly.
I would like to have a code in my command button "Filter" for such condition.
Any lead would be helpful.
this is the code, I am using in my listbox
Private Sub ListBox2_Change()
Dim listboxCounter As Integer
For listboxCounter = 0 To ListBox2.ListCount - 1
If ListBox2.Selected(listboxCounter) = True Then
List_Man.Cells(listboxCounter + 2, 2) = True
Else
List_Man.Cells(listboxCounter + 2, 2) = False
End If
Next
End Sub
this is the code for my userform
Private Sub UserForm_activate()
Dim xRow As Integer
Dim yows As Integer
For xRow = 2 To Last(1, List.Range("A:A"))
With ListBox1
.AddItem List.Cells(xRow, 3).Value
If List.Cells(xRow, 2) = True Then
.Selected(xRow - 2) = True
Else
.Selected(xRow - 2) = False
End If
End With
Next xRow
ListBox1.Height = (xRow - 1) * 15
For yrow = 2 To Last(1, List_Man.Range("A:A"))
With ListBox2
.AddItem List_Man.Cells(yrow, 3).Value
If List_Man.Cells(yrow, 2) = True Then
.Selected(yrow - 2) = True
Else
.Selected(yrow - 2) = False
End If
End With
Next yrow
ListBox2.Height = (xRow - 1) * 15
End Sub
I'm trying to create an array of option buttons (or check boxes if you find that works better) where only one option can be selected in each row and column.
I'm trying to do this so that a user can choose an order in which a certain list goes.
The following code takes the column headers in an excel sheet, and creates bunch of option buttons x columns across and x rows down.
Sub Option_Buttons()
Dim str As String
lCol = Sheets("Headers").UsedRange.Columns.Count
Dim OpBtn() As OptionButton
ReDim OpBtn(lCol, lCol) As OptionButton
Dim GrBx() As GroupBox
ReDim GrBx(lCol) As GroupBox
Dim i
Dim j
'
For i = 1 To lCol
Set GrBx(i) = Sheets("OPBTN").GroupBoxes.Add(Cells(i, 1).Left, _
Cells(i, 1).Top, lCol * 50, 17.25)
With GrBx(i)
.Caption = ""
'.Visible = False
End With
For j = 1 To lCol
Set OpBtn(i, j) = Sheets("OPBTN").OptionButtons.Add _
(Cells(i,j).Left, Cells(i, j).Top, 72, 17.25)
str = Sheets("Turf").Cells(1, j)
check = OpBtn(i, j).Value
With OpBtn(i, j)
.Caption = str
.Value = xlOff '
.LinkedCell = "'OData'!" & Sheets("OData").Cells(i, 1).Address
.Display3DShading = False
End With
Next
Next
End Sub
Is there any way I can make it so that only one option can exist in each row AND column? (so if there are 5 column headers, there are 25 option buttons of which only 5 can be selected).
Is there any way to deal with the option that a user doesn't want a header selected?
I'm trying to avoid all possible uses of the controls tab because this is part of a macro that needs to be used by completely excel illiterate people and needs to be applied to highly variable
I was able to accomplish this using checkboxes. The key was to name the checkboxes using R1C1 notation and assigning a macro (ManageCheckBoxes) to all the checkboxes. After identifying what checkbox was clicked using Application.Caller I iterate over all the checkboxes parsing their names to identify which rows and columns they are in.
Sub Option_Buttons()
Dim str As String
Dim r As Integer, c As Integer
Dim check As CheckBox
lCol = Sheets("Headers").UsedRange.Columns.Count
With Sheets("OPBTN")
For r = 1 To lCol
For c = 1 To lCol
Set check = .CheckBoxes.Add(.Cells(r, c).Left, .Cells(r, c).Top, 72, 17.25)
str = Sheets("Turf").Cells(r, c)
With check
.Caption = str
.Value = xlOff '
.Name = "R" & r & "C" & c
.Display3DShading = False
.OnAction = "ManageCheckBoxes"
End With
Next
Next
End With
End Sub
Sub ManageCheckBoxes()
Dim arrCaller As Variant, arrCheck As Variant
Dim check As CheckBox, ckCaller As CheckBox
arrCaller = getRC(Application.Caller)
With Sheets("OPBTN")
Set ckCaller = .CheckBoxes(Application.Caller)
For Each check In .CheckBoxes
If ckCaller.Name <> check.Name Then
If check.Name Like "R#*C#*" Then
arrCheck = getRC(check.Name)
If arrCheck(0) = arrCaller(0) Or arrCheck(1) = arrCaller(1) Then
check.Value = False
End If
End If
End If
Next
End With
End Sub
Function getRC(sName As String)
Dim a(1) As Long
Dim arr As Variant
arr = Split(sName, "C")
a(0) = Right(arr(0), Len(arr(0)) - 1)
a(1) = arr(1)
getRC = a
End Function
use GroupName property of option buttons. GroupName property determines the group of option button. user will be able to select only one option button from the group.
Set same groupname for your five option buttons and same for other five.
For Example :
Option1 GroupName: grp1
Option2 GroupName: grp1
Option3 GroupName: grp2
Option4 GroupName: grp2
in the above case user will be able to select one from option1 and option2. one button from option3 and option4.
I am trying to set up my user form to do a loop or look up to reference my table which is on a sheet and is a large data base.
I want my user form to look up what I type and then auto fill in the other textboxes so that I can limit the number of duplicates and make it more stream lined.
My code is as shown below is embedded into Textbox1 and is set up to run the code after change. It is still not working and I have worked for many days and weeks trying to figure this out.
Option Explicit
Dim id As String, i As String, j As Integer, flag As Boolean
Sub GetDataA()
If Not IsNumeric(UserForm1.TextBox1.Value) Then
flag = False
i = 0
id = UserForm1.TextBox1.Value
Do While Cells(i + 1, 1).Value <> ""
If Cells(i + 1, 1).Value = id Then
flag = True
For j = 2 To 7
UserForm1.Controls("TextBox" & j).Value = Cells(i + 1, j).Value
Next j
End If
i = i + 1
Loop
If flag = False Then
For j = 5 To 10
UserForm1.Controls("TextBox" & j).Value = ""
Next j
End If
Else
End If
End Sub
you may want to adopt this refactoring of your code
Option Explicit
Sub GetDataA()
Dim j As Integer
Dim f As Range
With UserForm1 '<--| reference your userform
If Not IsNumeric(.TextBox1.Value) Then Exit Sub '<--| exit sub if its TextBox1 value is not a "numeric" one
Set f = Range("A1", Cells(Rows.Count, 1).End(xlUp)).Find(what:=.TextBox1.Value, LookIn:=xlValues, lookat:=xlWhole) '<--| try and find its TextBox1 value along column "A" cells from row 1 down to last not empty one
If f Is Nothing Then '<--| if not found
For j = 5 To 10
.Controls("TextBox" & j).Value = ""
Next j
Else '<--| if found
For j = 2 To 7
.Controls("TextBox" & j).Value = f.Offset(, j - 1).Value
Next j
End If
End With
End Sub
note: if this sub is actually inside UserForm1 code pane than you can change With UserForm1 to With Me
I'm creating a workbook, which tracks available rentals per month. It is divided into 12 sheets, one for each month. The first three columns of each sheet track the type of accommodation, number of bedrooms and what's included in the rental price. The concept there is that there will be a drop-down combo box that allows the user to fill in with a point-and-click option rather than typing things out in order to reduce input errors.
I set up a fixed array, the contents in which changes depending on what column that active cell is in, and then the array is assigned to the combo box. The code lives in the Sheet1 Module under the combo box code and the ThisWorkbook module calls it under SheetSelectionChange, so as to avoid repeating the code in each sheet.
A Standard Module makes the array public
All 12 combo boxes share the same name, cboOptions, and they populate correctly, regardless of what sheet is chosen. My problem is that none of the combo boxes return the listindex value of the choice that's made, regardless of the code telling it to do so. I've been testing to see the value of the position returned against the value of the position chosen, but I have not been able to establish a pattern. I thought about clearing the variables and arrays, thinking that might be what's messing with the code, but it seems to be having no effect. I've read what I could on the issue, but I'm out of ideas on what might be the problem...thank you in advance!
Code in Sheet1 module:
Private Sub cboOptions_Change()
Erase myarray()
cboOptions.Visible = True
cboOptions.Enabled = True
cboOptions.Clear
n = ActiveCell.Row
If n >= 3 And n < 10000 Then
If ActiveSheet.Range(ActiveCell.Address).Address = Range("A" & n).Address Then
myarray(1) = "Apartment"
myarray(2) = "Room"
myarray(3) = "Townhouse"
myarray(4) = "House"
ElseIf ActiveSheet.Range(ActiveCell.Address).Address = Range("B" & n).Address Then
myarray(1) = "1"
myarray(2) = "2"
myarray(3) = "3"
myarray(4) = "4"
myarray(5) = "5"
ElseIf ActiveSheet.Range(ActiveCell.Address).Address = Range("C" & n).Address Then
myarray(1) = "Heat & Water"
myarray(2) = "All-inclusive"
Else
cboOptions.Enabled = False
cboOptions.Visible = False
End If
End If
'ActiveSheet.cboOptions.ListIndex = 0
'Dim x As Long
'MsgBox ActiveSheet.Name
With ActiveSheet
.cboOptions.Left = .Range(ActiveCell.Address).Left
.cboOptions.Top = .Range(ActiveCell.Address).Top
.cboOptions.List = myarray()
With .cboOptions
'the problem is that x needs to get assigned a value from the combo box before it continues to execute
x = .List(.ListIndex)
'MsgBox x
End With
.Range(ActiveCell.Address) = x 'myarray(x)
.Columns(ActiveCell.Column).ColumnWidth = cboOptions.Width * 0.18
x = 0
Erase myarray()
End With
End Sub
Code in ThisWorkbook:
Sub Workbook_SheetSelectionChange(ByVal sh As Object, ByVal Target As Range)
Application.Run "Sheet1.cboOptions_Change"
End Sub
Code in Module1:
Option Explicit
Public myarray(0 To 5) As String
The nature of the problem seems to be that using more than one array for one combo box breaks down how the listindex values are calculated. I broke down the code to its component features to see if the issue persisted
1) Made a new file and put the code in Sheet1
2) Made separate fixed arrays for each kind of input
3) Created a separate routine for each kind of input
Using ON ERROR RESUME NEXT at the beginning of each routine overlooks the error and the code works properly. Alternatively, putting in a break where the integer variable is given the listindex value of the combo box allows the user to make a choice and assign a value to the integer variable, before continuing. Otherwise, its default value is -1 and returns an error; using .list(.listindex) did not make any difference, suggesting that the code needs to wait for user input (using a combobox event other than Change?).
May just need to establish a separate combo box for each column. Anyway, the code below is the sticks-and-stones version of the above, for a single sheet, and it will do the job if applied to each sheet module in the workbook:
Sub monthnames()
'add month names to the first cell of each sheet
Dim n As Integer
'Sheets(1).Activate
For n = 1 To 12
Sheets.Add After:=ActiveSheet
ThisWorkbook.Sheets(n).Cells(1, 1) = MonthName(n)
Next
End Sub
Private Sub cboOptions_Change()
Dim myarray(1 To 4) As String
Dim myarray2(1 To 5) As String
Dim myarray3(1 To 2) As String
cboOptions.Enabled = True
cboOptions.Visible = True
Dim n As Integer
n = ActiveCell.Row
If n >= 3 And n < 10000 Then
If Range(ActiveCell.Address).Address = Range("A" & n).Address Then
myarray(1) = "Apartment"
myarray(2) = "Room"
myarray(3) = "Townhouse"
myarray(4) = "House"
cboOptions.List = myarray()
inputdata myarray(), n
ElseIf Range(ActiveCell.Address).Address = Range("B" & n).Address Then
myarray2(1) = "1"
myarray2(2) = "2"
myarray2(3) = "3"
myarray2(4) = "4"
myarray2(5) = "5"
cboOptions.List = myarray2()
inputdata2 myarray2(), n
ElseIf Range(ActiveCell.Address).Address = Range("C" & n).Address Then
myarray3(1) = "Heat & Water"
myarray3(2) = "All-inclusive"
cboOptions.List = myarray3()
inputdata3 myarray3(), n
Else
cboOptions.Enabled = False
cboOptions.Visible = False
End If
End If
End Sub
Sub inputdata(myarray, n) 'myarray3, )
On Error Resume Next
Dim x As Integer
cboOptions.Left = Range(ActiveCell.Address).Left
cboOptions.Top = Range(ActiveCell.Address).Top
Columns(ActiveCell.Column).ColumnWidth = cboOptions.Width * 0.18
If Range(ActiveCell.Address).Address = Range("A" & n).Address Then
x = cboOptions.ListIndex + 1
Range(ActiveCell.Address) = myarray(x)
Else
Exit Sub
End If
End Sub
Sub inputdata2(myarray2, n)
On Error Resume Next
Dim y As Integer
cboOptions.Left = Range(ActiveCell.Address).Left
cboOptions.Top = Range(ActiveCell.Address).Top
Columns(ActiveCell.Column).ColumnWidth = cboOptions.Width * 0.18
If Range(ActiveCell.Address).Address = Range("B" & n).Address Then
y = cboOptions.ListIndex + 1
Range(ActiveCell.Address) = myarray2(y)
Else
Exit Sub
End If
End Sub
Sub inputdata3(myarray3, n)
On Error Resume Next
Dim z As Integer
cboOptions.Left = Range(ActiveCell.Address).Left
cboOptions.Top = Range(ActiveCell.Address).Top
Columns(ActiveCell.Column).ColumnWidth = cboOptions.Width * 0.18
If Range(ActiveCell.Address).Address = Range("C" & n).Address Then
z = cboOptions.ListIndex + 1
Range(ActiveCell.Address) = myarray3(z)
Else
Exit Sub
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Call cboOptions_Change
End Sub
I have a table with three columns,
ID, Name and Date
then I create a userform with textbox ID and Name.
how could I display the Name of similar ID from the table with latest Date when I key in the ID in the userform? (similar ID will have different names, but I want to display the one with latest date in the table)
thanks in advance for all the help
coding for the textbox1
Private Sub TextBox1_Change()
getdata
End Sub
coding for the getdata module
Sub getdata()
If IsNumeric(UserForm1.TextBox1.Value) Then
flag = False
i = 0
id = UserForm1.TextBox1.Value
Do While Cells(i + 1, 1).Value <> ""
If Cells(i + 1, 1).Value = id Then
flag = True
For j = 2 To 3
UserForm1.Controls("textbox" & j).Value = Cells(i + 1, j).Value
Next j
End If
i = i + 1
Loop
If flag = False Then
For j = 2 To 3
UserForm1.Controls("TextBox" & j).Value = ""
Next j
End If
Else
ClearForm
End If
End Sub
This should do it for you. This routine goes in your userform code module:
Private Sub TextBox1_AfterUpdate()
TextBox2 = Evaluate("=INDEX(B2:B999,MATCH(MAX((IF(A2:A999=" & TextBox1 & _
",1)*(C2:C999)),1),IF(A2:A999=" & TextBox1 & _
",1)*(C2:C999),))")
End Sub
It assumes your data are in columns A, B, and C. It also assumes your data do not extend past row 999; if they do, then increase the 999's in the formula to what is appropriate.
TextBox1 is for the ID.
TextBox2 is for the Name.
Note that this code is placed in the AfterUpdate event procedure. This is different than your sample code. You used the Change event procedure. The difference is that Change fires on each keystroke while AfterUpdate fires only after the full text is confirmed for the textbox.
Note that you should still add error checking for the case where the ID is not numeric and also for the case where the numeric ID does not match. The code above is simply for demonstrating the technique to display the looked-up value. If you wish for me to flesh it out more, please let me know.
UPDATE
I went ahead and fleshed it out with the error checking:
Private Sub TextBox1_AfterUpdate()
GetData
End Sub
Public Sub GetData()
Dim v, w
On Error Resume Next
v = Evaluate("=INDEX(B2:B999,MATCH(MAX((IF(A2:A999=" & TextBox1 & _
",1)*(C2:C999)),1),IF(A2:A999=" & TextBox1 & _
",1)*(C2:C999),))")
w = Evaluate("MAX((IF(A2:A999=" & TextBox1 & ",1)*(C2:C999)))")
If IsArray(v) Or IsError(v) Then v = "ID not found.": w = ""
TextBox2 = v
TextBox3 = "": TextBox3 = CDate(w)
End Sub
UPDATE 2
In the fleshed out version directly above, I added support for the associated date in TextBox3.
You could read the whole range in when the userform opens, sort it, then find the first ID.
Private mvaData As Variant
Private Sub TextBox1_AfterUpdate()
Me.TextBox2.Text = vbNullString
Me.TextBox3.Text = vbNullString
GetData
End Sub
Public Sub GetData()
Dim i As Long
For i = LBound(mvaData, 1) To UBound(mvaData, 1)
If mvaData(i, 1) = Val(Me.TextBox1.Text) Then
Me.TextBox2.Text = mvaData(i, 2)
Me.TextBox3.Text = mvaData(i, 3)
Exit For 'stop after the first one - largest date
End If
Next i
End Sub
Private Sub UserForm_Initialize()
Dim i As Long, j As Long
Dim lId As Long, sDesc As String, dtDate As Date
'store the data in a variable when the forms opens
mvaData = Sheet1.Range("A1:C5")
'sort with larger dates on top
For i = LBound(mvaData, 1) To UBound(mvaData, 1) - 1
For j = i To UBound(mvaData, 1)
If mvaData(i, 3) < mvaData(j, 3) Then
lId = mvaData(j, 1)
sDesc = mvaData(j, 2)
dtDate = mvaData(j, 3)
mvaData(j, 1) = mvaData(i, 1)
mvaData(j, 2) = mvaData(i, 2)
mvaData(j, 3) = mvaData(i, 3)
mvaData(i, 1) = lId
mvaData(i, 2) = sDesc
mvaData(i, 3) = dtDate
End If
Next j
Next i
End Sub