I have this code and I need textbox 9 and 10 to be number vlaues when entering in my excel table any idea how I can fix this?
Sub FillRanges(ws As Worksheet, L As Long)
With ws
.Range("C" & L).Value = (Now)
.Range("D" & L).Value = Me.TextBox2
.Range("E" & L).Value = Me.TextBox3
.Range("F" & L).Value = Me.TextBox4
.Range("G" & L).Value = Me.TextBox5
.Range("K" & L).Value = Me.ComboBox1
.Range("L" & L).Value = Me.ComboBox2
.Range("M" & L).Value = Me.ComboBox3
.Range("N" & L).Value = Me.TextBox9
.Range("O" & L).Value = Me.TextBox10
.Range("R" & L).Value = Me.TextBox39
.Range("P" & L).Value = Me.TextBox40
End With
End Sub
You can use a convert function like CDbl(). It would be something like:
Sub FillRanges(ws As Worksheet, L As Long)
With ws
.Range("C" & L).Value = (Now)
.Range("D" & L).Value = Me.TextBox2
.Range("E" & L).Value = Me.TextBox3
.Range("F" & L).Value = Me.TextBox4
.Range("G" & L).Value = Me.TextBox5
.Range("K" & L).Value = Me.ComboBox1
.Range("L" & L).Value = Me.ComboBox2
.Range("M" & L).Value = Me.ComboBox3
.Range("N" & L).Value = CDbl(Me.TextBox9)
.Range("O" & L).Value = CDbl(Me.TextBox10)
.Range("R" & L).Value = Me.TextBox39
.Range("P" & L).Value = Me.TextBox40
End With
There are also other convert functions. CInt()(integer), CLng()(long) and CDec()(decimal).
I think it's preferable to validate user input before using (writing) it
so you may want to write some quite simple user input validation subs and call them from within controls change event handler, like follows:
Option Explicit
Private Sub TextBox9_Change()
ValidateNumericInput Me.TextBox9, 0, 10.4 '<--| as soon as this control text changes, call 'ValidateNumericInput' to validate it
End Sub
Private Sub ValidateNumericInput(tb As MSForms.TextBox, minVal As Double, maxVal As Double)
Dim errMsg As String
With tb
If Len(.Text) > 0 Then '<-- proceed only if there's some text to validate!
Select Case True
Case Not IsNumeric(.value) '<--| if not a "numeric" input
errMsg = "please enter a number"
Case CDbl(.Text) < minVal Or CDbl(.Text) > maxVal '<--| if "numeric" input exceeds passed range
errMsg = "please enter a number within " & minVal & " and " & maxVal
End Select
If errMsg <> "" Then '<--| if error message has been written
MsgBox "invalid input in " & tb.name & vbCrLf & vbCrLf & errMsg, vbCritical + vbExclamation + vbOKOnly, "Invalid input" '<--| infrm the user
.Text = "" '<--| delete textbox input
End If
End If
End With
End Sub
where I assumed a Double type input would be needed, but you can easily adapt it to other types
so, you may then add such other subs as:
ValidateStringInput(tb As MSForms.TextBox, validStrings() as String)
and the likes...
Related
I have cells that are supposed to be 0 I believe. 7.45058059692383E-12.
How do I make these 0 in my code?
Sheets("MainData").Range("C" & i) = Sheets("CM_MainData").Range("C" & i)
I thought converting NumberFormat to 0 may help but it did not work.
Sheets("MainData").Range("C" & i) = Sheets("CM_MainData").Range("C" & i).NumberFormat = "0.00"
Instead the result is FALSE
Please Help!
Full code:
Sub CopyData()
Worksheets("MainData").Rows("2:" & Rows.Count).ClearContents
'Copy data from the CM Commentary File to Template
Application.ScreenUpdating = False
Set MainDataCM = Workbooks.Open(Sheets("Input").Range("B3") & Sheets("Input").Range("B6"))
MainDataCM.Sheets("Main Data").Copy After:=ThisWorkbook.Sheets(1)
MainDataCM.Close savechanges:=False
Application.ScreenUpdating = True
Sheets("Main Data").Name = "CM_MainData"
Worksheets("CM_MainData").Visible = False
'Read the CM_MainData tab and copy the required columns in the MainData tab
Dim k As Long
k = Sheets("CM_MainData").Range("A1", Sheets("CM_MainData").Range("A1").End(xlDown)).Rows.Count
Debug.Print (k)
i = 2
While i <= k
Sheets("MainData").Range("A" & i) = Sheets("CM_MainData").Range("A" & i)
Sheets("MainData").Range("B" & i) = Sheets("CM_MainData").Range("B" & i)
Sheets("MainData").Range("C" & i) = Sheets("CM_MainData").Range("C" & i).NumberFormat = "0.00"
Sheets("MainData").Range("D" & i) = Sheets("CM_MainData").Range("D" & i)
Sheets("MainData").Range("E" & i) = Sheets("CM_MainData").Range("C" & i) * 1000
Sheets("MainData").Range("F" & i) = Sheets("CM_MainData").Range("H" & i)
'Sheets("MainData").Range("E" & i).NumberFormat = "0.00"
If Sheets("MainData").Range("F" & i) = "" Then
Sheets("MainData").Range("F" & i) = "RBC INVESTOR SERV O/H & MISC"
End If
i = i + 1
Wend
Worksheets("Macro").Activate
Worksheets("Macro").Select
MsgBox "Step 1 Completed"
End Sub
Value transfer:
Sheets("MainData").Range("C" & i).Value = Sheets("CM_MainData").Range("C" & i).Value
Number format (a separate step, and does not change the underlying value):
Sheets("MainData").Range("C" & i).NumberFormat = "0.00"
Or use WorksheetFunction.Round (does change the underlying value).
Sheets("MainData").Range("C" & i).Value = WorksheetFunction.Round(Sheets("CM_MainData").Range("C" & i).Value, 2)
I have a data entry form that let's users enter the data into specific cells. What i want is a way to track changes to the cell values. When the data entered initially through the entry form, i don't want that information to be tracked. However, if the user tries to change/edit the data that was entered then i want to add a comment to show the initial value and the amended one as well.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim singlecell As Range
If Target.Cells.CountLarge > 1000 Then Exit Sub
For Each singlecell In Target
If singlecell.Comment Is Nothing Then
singlecell.AddComment Now & " - " & singlecell.Value & " - " & Environ("UserName")
Else
singlecell.Comment.Text _
vbNewLine & Now & " - " & singlecell.Value & " - " & Environ("UserName") _
, Len(singlecell.Comment.Text) + 1 _
, False
End If
singlecell.Comment.Shape.TextFrame.AutoSize = True
Next singlecell
End Sub
The code i tried adds a comment when the information from the entry form is submitted. However I don't need the comment to show just yet, I only want it when the user changes the initial cell value.
you can use a helper array to temporary store all of current cell comments and get the sensitive text out of the last recorded comment to compare with current cell content
Private Sub Worksheet_Change(ByVal Target As Range)
Dim singleCell As Range
Dim commentsArray As Variant 'array to hold all singleCell comments
Dim oldText As String ' string to hold last comment sensitive content
If Target.Cells.CountLarge > 1000 Then Exit Sub
For Each singleCell In Target
If singleCell.Comment Is Nothing Then
singleCell.AddComment Now & " - " & singleCell.Value & " - " & Environ("UserName")
Else
commentsArray = Split(singleCell.Comment.Text, vbNewLine) ' fill the array with current singleCell comments
oldText = CStr(Split(commentsArray(UBound(commentsArray)), " - ")(1)) ' extract last recorded comment sensitive text
'update comment if current cell value differs from last recorded comment sensitive text
If oldText <> CStr(singleCell.Value2) Then _
singleCell.Comment.Text _
vbNewLine & Now & " - " & singleCell.Value & " - " & Environ("UserName") _
, Len(singleCell.Comment.Text) + 1 _
, False
End If
singleCell.Comment.Shape.TextFrame.AutoSize = True
Next
End Sub
Copy and create the same table in same sheet, have it hidden ,
Sub CopyCurrentTable()
Application.ScreenUpdating = False
With shtMapping
.Range("E4:G1000").ClearContents 'which value to which value you are copying
.Range("B4:D" & GetLastRow(shtMapping, "B", 4)).Copy ' starting postion
.Range("E4").PasteSpecial xlPasteAll
Application.CutCopyMode = False
End With
End Sub
Sub LogAuditTrail()
Dim colOld As Collection
Dim colNew As Collection
Dim objNew As ClsMapping
Dim objOld As ClsMapping
Set colOld = getMappingData("E")
Set colNew = getMappingData("B")
Dim sTS As String
sTS = Format(Now, "dd-mmm-yyy hh:mm:ss")
For Each objNew In colNew
'Detect Items Changed
If ItemIsInCollection(colOld, objNew.getKey) Then
Set objOld = colOld(objNew.getKey)
If objNew.isDifferent(objOld) Then
Call PlotToAudit(objNew, objOld, sTS, "Change")
End If
Else
'Detect Items Added
Set objOld = New ClsMapping
Call PlotToAudit(objNew, objOld, sTS, "New")
End If
Next objNew
'Detect Items removed
For Each objOld In colOld
If Not ItemIsInCollection(colNew, objOld.getKey) Then
Set objNew = New ClsMapping
Call PlotToAudit(objNew, objOld, sTS, "Removed")
End If
Next objOld
End Sub
Sub PlotToAudit(obj1 As ClsMapping, obj2 As ClsMapping, sTS As String, sType As String)
Dim lRow As Long
lRow = shtAudit.Range("B1048576").End(xlUp).Row
If lRow = 3 Then
lRow = 5
ElseIf lRow = 1048576 Then
MsgBox "Audit sheet is full. Contact Support." & vbNewLine & "No audit trail will be saved", vbCritical, "ERROR"
Exit Sub
Else
lRow = lRow + 1
End If
With shtAudit
.Unprotect g_sPassword
.Range("B" & lRow).value = Application.UserName & "(" & Environ("USERNAME") & ")"
.Range("C" & lRow).value = sTS
.Range("D" & lRow).value = sType
Select Case sType
Case "Removed"
.Range("E" & lRow).value = ""
.Range("F" & lRow).value = ""
.Range("G" & lRow).value = ""
.Range("H" & lRow).value = obj2.FundCode
.Range("I" & lRow).value = obj2.Subs
.Range("J" & lRow).value = obj2.Reds
Case "New"
.Range("E" & lRow).value = obj1.FundCode
.Range("F" & lRow).value = obj1.Subs
.Range("G" & lRow).value = obj1.Reds
.Range("H" & lRow).value = ""
.Range("I" & lRow).value = ""
.Range("J" & lRow).value = ""
Case "Change"
.Range("E" & lRow).value = obj1.FundCode
.Range("F" & lRow).value = obj1.Subs
.Range("G" & lRow).value = obj1.Reds
.Range("H" & lRow).value = obj2.FundCode
.Range("I" & lRow).value = obj2.Subs
.Range("J" & lRow).value = obj2.Reds
End Select
With .Range("B" & lRow & ":J" & lRow)
.Interior.Color = vbWhite
.Borders.LineStyle = xlContinuou
End With
.Protect g_sPassword
End With
End Sub
I am trying to make an excel user form through VBA. It should:
Take the data entered in the textboxes and put it into the next empty row in a specific sheet
In some textBoxes (specifically TextBox3, TextBox4, TextBox5 and TextBox6) should only be entered date data type. If the user enters any other data format an error message should appear and the form should close, not filling the next empty row that it was about to fill in the sheet.
All textBoxes should have an input, except TextBox5 and TextBox6, these could be empty, if any other textbox is empty an error message should appear.
After the proper inputs are made a confirmation msgbox should appear for the user to check any error, before the form closes
Step 1 I've menaged to do but 2 and 3 are not working properly with what I have so far (I can me more specific with the errors if needed). I'm new to VBA and programming and think I've messed with the 'Ifs'. Thanks in advence for any help!
Private Sub CommandButton1_Click()
'Check if data in TextBox is date
Private Sub TextBox3_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If Not ((IsDate(TextBox3.Text)) And (IsDate(TextBox4.Text)) And (IsDate(TextBox5.Text)) And (IsDate(TextBox6.Text))) Then
MsgBox "Date Required"
Cancel = True
Else
'Last ditch validation before committing input values to document.
Dim booConfirmation As Boolean
'Check for data
If Len(TextBox1.Text) = 0 Or Len(TextBox2.Text) = 0 Or Len(TextBox3.Text) = 0 Or Len(TextBox4.Text) = 0 Or Len(TextBox7.Text) = 0 Or Len(TextBox8.Text) = 0 Or Len(TextBox9.Text) = 0 Or Len(TextBox10.Text) = 0 Or Len(TextBox11.Text) = 0 Then
MsgBox "Empty entries", vbOKOnly, "Input Error"
End If
'Display name so user can check and confirm.
booConfirmation = MsgBox("Are the entries " & TextBox1 & " " & TextBox2 & " " & TextBox3 & " " & TextBox4 & " " & TextBox7 & " " & TextBox8 & " " & TextBox9 & " " & TextBox10 & " " & TextBox11 & "correct?", vbYesNo)
'If booConfirmation Then
If booConfirmation = vbNo Then
MsgBox "Please correct the entries"
Set ws = Sheets("Inputs")
LastRow = ws.Range("B" & Rows.Count).End(xlUp).Row + 1
ws.Range("B" & LastRow).Value = "" 'if entries are incorrect erase the data that should be entered into the sheet'
ws.Range("C" & LastRow).Value = ""
ws.Range("D" & LastRow).Value = ""
ws.Range("E" & LastRow).Value = ""
ws.Range("F" & LastRow).Value = ""
ws.Range("G" & LastRow).Value = ""
ws.Range("H" & LastRow).Value = ""
ws.Range("I" & LastRow).Value = ""
ws.Range("J" & LastRow).Value = ""
ws.Range("K" & LastRow).Value = ""
ws.Range("L" & LastRow).Value = ""
Exit Sub
Else
Set ws = Sheets("Inputs")
LastRow = ws.Range("B" & Rows.Count).End(xlUp).Row + 1
ws.Range("B" & LastRow).Value = TextBox1.Text 'Adds the TextBox1 into Col B & Last Blank Row
ws.Range("C" & LastRow).Value = TextBox2.Text 'Adds the TextBox2 into Col C & Last Blank Row
ws.Range("D" & LastRow).Value = TextBox3.Text
ws.Range("E" & LastRow).Value = TextBox4.Text
ws.Range("F" & LastRow).Value = TextBox5.Text
ws.Range("G" & LastRow).Value = TextBox6.Text
ws.Range("H" & LastRow).Value = TextBox7.Text
ws.Range("I" & LastRow).Value = TextBox8.Text
ws.Range("J" & LastRow).Value = TextBox9.Text
ws.Range("K" & LastRow).Value = TextBox10.Text
ws.Range("L" & LastRow).Value = TextBox11.Text
End If
End If
Unload Me
End Sub
This is not an answer this is just to help you see it more clearly
All I've done is re-arrange your code and provide consistent indentation
You had, no end sub for one procedure and code mixed up between the two, with an endif that belonged in one in the other
Anyway - this is your code ... with only minor changes .... make exit procedure just check the 1 field
Private Sub TextBox3_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'Check if data in TextBox is date
If Not (IsDate(TextBox3.Text)) Then ' And (IsDate(TextBox4.Text)) And (IsDate(TextBox5.Text)) And (IsDate(TextBox6.Text))) Then
MsgBox "Date Required"
Cancel = True
Else
End If
End Sub
Private Sub CommandButton1_Click()
'Last ditch validation before committing input values to document.
Dim booConfirmation As Boolean
'Check for data
'Display name so user can check and confirm.
booConfirmation = MsgBox("Are the entries " & TextBox1 & " " & TextBox2 & " " & TextBox3 & " " & TextBox4 & " " & TextBox7 & " " & TextBox8 & " " & TextBox9 & " " & TextBox10 & " " & TextBox11 & "correct?", vbYesNo)
'If booConfirmation Then
If booConfirmation = vbNo Then
MsgBox "Please correct the entries"
Set ws = Sheets("Inputs")
LastRow = ws.Range("B" & Rows.Count).End(xlUp).Row + 1
ws.Range("B" & LastRow).Value = "" 'if entries are incorrect erase the data that should be entered into the sheet'
ws.Range("C" & LastRow).Value = ""
ws.Range("D" & LastRow).Value = ""
ws.Range("E" & LastRow).Value = ""
ws.Range("F" & LastRow).Value = ""
ws.Range("G" & LastRow).Value = ""
ws.Range("H" & LastRow).Value = ""
ws.Range("I" & LastRow).Value = ""
ws.Range("J" & LastRow).Value = ""
ws.Range("K" & LastRow).Value = ""
ws.Range("L" & LastRow).Value = ""
Exit Sub
Else
Set ws = Sheets("Inputs")
LastRow = ws.Range("B" & Rows.Count).End(xlUp).Row + 1
ws.Range("B" & LastRow).Value = TextBox1.Text 'Adds the TextBox1 into Col B & Last Blank Row
ws.Range("C" & LastRow).Value = TextBox2.Text 'Adds the TextBox2 into Col C & Last Blank Row
ws.Range("D" & LastRow).Value = TextBox3.Text
ws.Range("E" & LastRow).Value = TextBox4.Text
ws.Range("F" & LastRow).Value = TextBox5.Text
ws.Range("G" & LastRow).Value = TextBox6.Text
ws.Range("H" & LastRow).Value = TextBox7.Text
ws.Range("I" & LastRow).Value = TextBox8.Text
ws.Range("J" & LastRow).Value = TextBox9.Text
ws.Range("K" & LastRow).Value = TextBox10.Text
ws.Range("L" & LastRow).Value = TextBox11.Text
End If
Unload Me
End Sub
Final One:enter image description hereI want to insert blank row with a specific column range above a particular row.
For example:
There were 2 sets of data in a single sheet ,ie, 1st set col A to Col E and 2nd set Col F to Col J. I need to compare Column Ai with Column Fi (where i indicates the position of row) and if both values are same then the comparison can be proceeded like Bi with Gi, Ci with Hi and so and so and if not, I need to shift that set of 2nd data Fi to Ji to next row..ie. if the whole set is in 6th position I need to shift them down to 7th position and make the 6th position of Fi to Ji blank....
Sub Dcompare()
Dim endRow As Long
Dim lRow As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(1)
endRow = Sheet1.Range("A999999").End(xlUp).Row
For i = 2 To endRow
If Sheet1.Range("A" & i).Value = Sheet1.Range("F" & i).Value Then
Sheet1.Range("K" & i).Value = "Yes"
Else
ws.Range("F" & i & ":J" & i).Offset(1, 0).Value = ws.Range("F" & i & ":J" & i).Value
ws.Range("F" & i & ":J" & i).Value = ""
End If
Next i
For j = 2 To endRow
If Sheet1.Range("K" & j).Value = "Yes" Then
If Sheet1.Range("B" & j).Value = Sheet1.Range("G" & j).Value Then
Sheet1.Range("L" & j).Value = "Yes"
Else
Sheet1.Range("L" & j).Value = "No"
End If
If Sheet1.Range("C" & j).Value = Sheet1.Range("H" & j).Value Then
Sheet1.Range("M" & j).Value = "Yes"
Else
Sheet1.Range("M" & j).Value = "No"
End If
If Sheet1.Range("D" & j).Value = Sheet1.Range("I" & j).Value Then
Sheet1.Range("N" & j).Value = "Yes"
Else
Sheet1.Range("N" & j).Value = "No"
End If
If Sheet1.Range("E" & j).Value = Sheet1.Range("J" & j).Value Then
Sheet1.Range("O" & j).Value = "Yes"
Else
Sheet1.Range("O" & j).Value = "No"
End If
End If
Next j
End Sub
------>Final Code Inserted---------
Sub Dcompare()
Dim endRow As Long
Dim ws As Worksheet
Dim dShift As Boolean
Set ws = ThisWorkbook.Worksheets(1)
endRow = ws.Range("A999999").End(xlUp).Row
For i = 2 To endRow + 1
If ws.Range("A" & i).Value = ws.Range("F" & i).Value Then
dShift = False
ws.Range("K" & i).Value = "Yes"
Else
If Not dShift Then
ws.Range("F" & i & ":J" & i).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
ws.Range("A" & i + 1 & ":E" & i + 1).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
endRow = endRow + 1
dShift = True
Else
dShift = False
End If
End If
j = i
If ws.Range("K" & j).Value = "Yes" Then
If ws.Range("B" & j).Value = ws.Range("G" & j).Value Then
ws.Range("L" & j).Value = "Yes"
Else
ws.Range("L" & j).Value = "No"
End If
If ws.Range("C" & j).Value = ws.Range("H" & j).Value Then
ws.Range("M" & j).Value = "Yes"
Else
ws.Range("M" & j).Value = "No"
End If
If ws.Range("D" & j).Value = ws.Range("I" & j).Value Then
ws.Range("N" & j).Value = "Yes"
Else
ws.Range("N" & j).Value = "No"
End If
If ws.Range("E" & j).Value = ws.Range("J" & j).Value Then
ws.Range("O" & j).Value = "Yes"
Else
ws.Range("O" & j).Value = "No"
End If
Else
End If
Next i
MsgBox "The value of endRow is : " & endRow, vbInformation
End Sub
Based on your explanations, this is what I interpret your challenge as:
Evaluate Ai with Fi --> Ei with Ji from left to right, and indicate in helper-columns whether the evaluation succeeded or not
If the first evaluation is Not Equal, offset the range Fi:Ji downwards exactly one row
If a range has been shifted down, the loop should evaluate this line but never shift it again regardless of outcome of the evaluation
This code satisfies those conditions (change i and other row variables to your needs):
Sub Dcompare()
Dim endRow As Long
Dim ws As Worksheet
Dim dShift As Boolean
Set ws = ThisWorkbook.Worksheets(1)
endRow = ws.Range("A999999").End(xlUp).Row
' Set initial value of helper columns to no - saves miniscule time and complexity in the loop
ws.Range("L" & 1 & ":O" & endRow).Value = "No"
For i = 1 To endRow
If ws.Range("A" & i).Value = ws.Range("F" & i).Value Then
dShift = False
ws.Range("L" & i).Value = "Yes"
Else
If Not dShift Then
ws.Range("F" & i & ":J" & i).Insert Shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
' Remember that we just shifted a row
dShift = True
Else
' Reset shift counter
dShift = False
End If
End If
For j = 2 To 4
If dShift Then Exit For
If ws.Cells(i, j).Value = ws.Cells(i, j + 5).Value Then ws.Cells(i, j + 11).Value = "Yes"
Next j
Next i
End Sub
However, it seems strange to me that you would want this functionality? Please confirm that it is correct. The behavior it yields in the worksheet is very strange.
Let me show with images. Orange background means the code will show the cell as a match. Green background means the code will show that the cell doesn't match.
Before the code it looks like this:
After the code it looks like this:
I would like to change the data values of textboxes by using a spinbutton
The data are written in an Excel table ..... could you explain to me which
syntax I should use or perhaps could you show me an example?
Private Sub SpinButton1_Change()
'Range("G15").Value = SpinButton1.Value
Dim I As Integer
For I = 2 To 10 Step 1
TextBox2.Value = Ws.Range("A"& I)
Next
Using the following code i gives a good result but but why do i need an msgbox ? Without msgbox it doesn't function ... strange ...
Private Sub SpinButton1_Change()
Dim I As Integer
For I = 2 To 10 Step 1
MsgBox ("La valeur de la Textbox" & I & " est de " & TextBox2)
ComboBox1.Value = Ws.Range("A" & I)
ActiveCell = Me.ComboBox1.Value
TextBox2.Value = Ws.Range("B" & I)
TextBox3.Value = Ws.Range("C" & I)
TextBox4.Value = Ws.Range("D" & I)
TextBox5.Value = Ws.Range("E" & I)
TextBox6.Value = Ws.Range("F" & I)
TextBox7.Value = Ws.Range("G" & I)
TextBox8.Value = Ws.Range("H" & I)
TextBox9.Value = Ws.Range("I" & I)
'Range("G15").Value = SpinButton1.Value
Next