Data validation for certain columns between other columns only - excel

Hey guys I am trying to change a code that I wrote for an excel vba Data validation tool. This is the first table i used:
Now I have another table with additional variables :
When I reuse the code from the first one (shown below) the columns on the right of length/width and height are also checked. I only want the three columns to be checked. I tried setting the variable lCol to 3 but then only C2 and the values below are checked. How can i apply the code only to the columns B/C/D without including the ones on the right without changing up the code completely?
Any help is appreciated!
Sub CheckColumnsTransportationMean()
Dim rng As Range
Dim lCol As Long, lRow As Long
Dim DblLengthMin As Double
Dim DblLengthMax As Double
Dim dynamicArray1() As String
Dim dynamicArray2() As String
Dim f1 As Integer
Dim f2 As Integer
f1 = 0
f2 = 0
ReDim Preserve dynamicArray1(0)
ReDim Preserve dynamicArray2(0)
DblLengthMax = 20000
DblLengthMin = 5
lCol = Range("C2").End(xltoRight).Column
lRow = Range("C2").End(xlDown).Row
For Each rng In Range("C2", Cells(lRow, lCol))
If IsNumeric(rng) = False Then
f1 = f1 + 1
rng.Interior.ColorIndex = 3
ReDim Preserve dynamicArray1(0 To f1)
dynamicArray1(f1) = "Row " & rng.Row & " Column " & rng.Column & " wrong
entry: " & rng.Value
End If
If IsNumeric(rng) And rng.Value > DblLengthMax Or rng.Value < DblLengthMin Then
f2 = f2 + 1
rng.Interior.ColorIndex = 46
ReDim Preserve dynamicArray2(0 To f2)
dynamicArray2(f2) = "Row " & rng.Row & " Column " & rng.Column & " wrong entry: " &
rng.Value
End If
Next rng
Inhalt1 = Join(dynamicArray1, vbCrLf)
MsgBox ("Wrong datatype! " & vbCrLf & vbCrLf & f1 & " Datatype Errors (marked red)" &
vbCrLf & "Only numbers can be entered. Check again" & vbCrLf & Inhalt1)
Inhalt2 = Join(dynamicArray2, vbCrLf)
MsgBox ("Entries out of range!" & vbCrLf & vbCrLf & f2 & " Range errors (marked
orange)" & vbCrLf & "The value is out of range. Check for unit [mm] " & vbCrLf &
Inhalt2)
End Sub

Related

Checking datatype in excel VBA

I wrote a code that checks whether the entered data is numeric with the isNumeric function. Now i want to specify and check whether it is an Integer. As far as i know, there is no function like isInteger. How can I check the datatype?
I posted a snippet of the code below, I hope it makes sense like this. If not please let me know.
Thank you for your help!
Sub CheckColumnsHardwareDefinition()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Hardware Definition")
Dim Target As Range
Dim Target2 As Range
Dim lr As Long
Dim lr2 As Long
Dim DblLengthMin As Double
Dim DblLengthMax As Double
Dim DblWeightMin As Double
Dim DblWeightMax As Double
Dim dynamicArray1() As String
Dim dynamicArray2() As String
Dim f1 As Integer
Dim f2 As Integer
f1 = 0
f2 = 0
DblLengthMax = 20000
DblLengthMin = 5
DblWeightMin = 0.0001
DblWeightMax = 10000
lr3 = Application.WorksheetFunction.Max( _
ws.Range("A" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("B" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("C" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("D" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("E" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("F" & ws.Rows.Count).End(xlUp).Row)
For Each Target3 In Range("A2:F" & lr3)
If IsEmpty(Target3) Then
Target3.Interior.ColorIndex = 8
End If
Next Target3
lr = Application.WorksheetFunction.Max( _
ws.Range("C" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("D" & ws.Rows.Count).End(xlUp).Row, _
ws.Range("E" & ws.Rows.Count).End(xlUp).Row)
For Each Target In Range("C2:E" & lr)
If **Not IsNumeric(Target)** Then
f1 = f1 + 1
Target.Interior.ColorIndex = 3
ReDim Preserve dynamicArray1(0 To f1)
dynamicArray1(f1) = "Row " & Target.Row & " Column " & Target.Column & " wrong
entry: " & Target.Value
End If
If **IsNumeric(Target)** And Target.Value > DblLengthMax Or Target.Value <
DblLengthMin
Then
f2 = f2 + 1
Target.Interior.ColorIndex = 46
ReDim Preserve dynamicArray2(0 To f2)
dynamicArray2(f2) = "Row " & Target.Row & " Column " & Target.Column & " wrong
entry: " & Target.Value
End If
Next Target
Inhalt1 = Join(dynamicArray1, vbCrLf)
MsgBox ("Wrong datatype! " & vbCrLf & vbCrLf & f1 & " Datatype Errors (marked
red)" & vbCrLf & "Only numbers can be entered. Check again" & vbCrLf & Inhalt1)
Inhalt2 = Join(dynamicArray2, vbCrLf)
MsgBox ("Entries out of range!" & vbCrLf & vbCrLf & f2 & " Range errors (marked
orange)" & vbCrLf & "The value is out of range. Check for unit [mm] " & vbCrLf &
Inhalt2)
End Sub
Let's take advantage of the "internal" casting of VBA
Function isInteger(val As Variant) As Boolean
Dim i As Integer
On Error GoTo EH
i = CInt(val)
If i = val Then ' check if it was cut or not
isInteger = True
Else
isInteger = False
End If
Exit Function
EH:
isInteger = False
End Function
As i was declared as integer i=val will cause an overflow and therefore the result is FALSE for 33000. If you do not want that you have to declare i as long and use CLng()
A short version would look like that
Function isInteger(val As Variant) As Boolean
On Error GoTo EH
isInteger = (val = CInt(val))
Exit Function
EH:
End Function

Paint cells using as reference text within a clicked cell

I have data like this in different cells in column F: 3RG-1S,22,45YM+1W,32VC,23
How can I do to once I click on a cell in column F, in this case, rows 3, 22, 45, 32 and 23 get painted in yellow?
Please help, I've been trying to do this, but I don't know how to use those formulas within VBA
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim celda As Range
Dim rowvalue As Integer
Dim column As Integer
Dim comas As Integer
Dim positioncoma As Integer
Dim newpositioncoma As Integer
Dim contenidocelda As String
Dim i As Long
Dim NumberOfHits As Long
Dim e As Integer
If ActiveCell.value <> "" Then
Range("A1:F500").Interior.ColorIndex = xlNone
Set celda = ActiveCell
column = ActiveCell.column
If column = 6 Then 'Only works when clicking cells in column F
For i = 1 To Len(celda)
If Mid(celda, i, 1) = "," Then
NumberOfHits = NumberOfHits + 1
End If
Next
comas = NumberOfHits 'Gets the number of commas in the selected cell
positioncoma = 0 'counter in zero
If comas <> 0 Then 'Loop to find the first numbers for each value within commas and paint those rows in yellow
For e = 1 To comas
newpositioncoma = "=IFERROR(FIND(" & Chr(34) & "," & Chr(34) & "," & celda & "," & positioncoma & "+1),LEN(" & celda & "))"
contenidocelda = "=MID(" & celda & "," & positioncoma & "+1," & newpositioncoma & "-" & positioncoma & "-1)"
rowvalue = "=LEFT(" & contenidocelda & ", MATCH(FALSE, ISNUMBER(MID(" & contenidocelda & ", ROW(INDIRECT(" & Chr(34) & "1:" & Chr(34) & "&LEN(" & contenidocelda & ")+1)), 1) *1), 0) -1)"
Range("A" & rowvalue & ":F" & rowvalue).Interior.ColorIndex = 36
positioncoma = newpositioncoma
Next e
Else
rowvalue = "=LEFT(celda,MATCH(FALSE,ISNUMBER(MID(celda,ROW(INDIRECT(" & Chr(34) & "1:" & Chr(34) & "&LEN(celda)+1)),1)*1),0)-1)"
End If
Else
Range("A1:F500").Interior.ColorIndex = xlNone 'unpaint cells once click somewhere else
End If
Else
Range("A1:F500").Interior.ColorIndex = xlNone 'unpaint cells if ActiveCell is empty
End If
End Sub
At the moment I'm using the following code that highlights cells but only when I have a simple number as a value. I can't find a way to get the numbers 3, 22, 45, 32 and 23 from a string like this: 3RG-1S,22,45YM+1W,32VC,23.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim rowvalue As Integer
Range("A4:xz90").Interior.ColorIndex = xlNone
If ActiveCell.column = 6 Then
rowvalue = ActiveCell.Row
Range("A" & rowvalue & ":xz" & rowvalue).Interior.ColorIndex = 19
If VarType(ActiveCell.Value) = 5 Then
rowvalue = ActiveCell.Value
Range("A" & rowvalue & ":xz" & rowvalue).Interior.ColorIndex = 35
End If
End If
End Sub
Example of my worksheet and result when I click cell F69
Dim v As Variant
Dim iRow As Long
Range("A1:F500").Interior.ColorIndex = xlNone
For Each v In Split(Range("f1"), ",")
iRow = Val(v)
If iRow > 0 Then
Range(Cells(iRow, "A"), Cells(iRow, "F")).Interior.Color = vbYellow
End If
Next

display only cells with value in Pop Up Form

the macro below takes two cell values (from first and second column)
and displays the column and there cell content in a Pop up Form
Im trying to add the condition that only the column and cell value is displayed if the cell contains value.
something like that =IF(A1<>"",result,"")
but I dont know how to implement that for all cells not only for a specific one.
Option Explicit
Const rangeForSearch = "G2"
Const rowTitles = 4
Dim arrTmp
Dim lastRow As Long, lastColumn As Long
Dim textForSearch As String, textForSearch_withoutSpaces As String
Dim strTmp As String
Dim i As Long, j As Long
Sub searchPerson()
Application.ScreenUpdating = False
With ActiveSheet
textForSearch = .Range(rangeForSearch)
If textForSearch = "" Then
MsgBox "Input text in cell """ & rangeForSearch & """ and try again!", vbCritical
Application.ScreenUpdating = True
Exit Sub
End If
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
lastColumn = .Cells(rowTitles, .Columns.Count).End(xlToLeft).Column
If lastRow <= rowTitles Or lastColumn <= 2 Then
MsgBox "Dataset is wrong! Check it and try again!", vbCritical
Application.ScreenUpdating = True
Exit Sub
End If
arrTmp = .Range(.Cells(rowTitles, "A"), .Cells(lastRow, lastColumn))
End With
'---------------------------------------
textForSearch_withoutSpaces = Replace(textForSearch, " ", "")
For i = LBound(arrTmp, 1) + 1 To UBound(arrTmp, 1)
strTmp = Replace(arrTmp(i, 1) & arrTmp(i, 2), " ", "")
If StrComp(textForSearch_withoutSpaces, strTmp, vbTextCompare) = 0 Then Exit For
Next i
If i = UBound(arrTmp, 1) + 1 Then
strTmp = textForSearch & vbCrLf & vbCrLf & "No dataset!"
Else
strTmp = textForSearch
For j = 3 To lastColumn
strTmp = strTmp & vbCrLf & vbCrLf & arrTmp(1, j) & ": " & arrTmp(i, j)
Next j
End If
Application.ScreenUpdating = True
MsgBox strTmp, , "Result"
End Sub
maybe
For j = 3 To lastColumn
If Not IsEmpty(arrTmp(i, j)) Then strTmp = strTmp & vbCrLf & vbCrLf & arrTmp(1, j) & ": " & arrTmp(i, j)
Next j

how to get a min and max value that is equal to a specific cell value?

I tried a formula to equal the ranges to a cell value. But the output is not as I expected. I think this should be in a for each loop not in a formula.
Does anyone have any ideas?
Here is the data:
Col:A Col:B
1001 abc
1002 abc
1003 abc
1004 abc
1005 abc
1006 xyz
1007 xyz
1008 xyz
1009 xyz
1010 xyz
Here is the formula that I tried:
"=CONCATENATE(MIN(IF(B2:B250=B2,A2:A250)),"-",MAX(IF(B2:B250=B2,A2:A250)))"
and the output is:
Col: A Col:B
1001-1010 abc
1002-1010 abc
1003-1010 abc
1004-1010 abc
1005-1010 abc
1006-1010 xyz
1007-1010 xyz
1008-1010 xyz
1009-1010 xyz
1010-1010 xyz
The output that i want to achieve is:
Col: A Column b
1001-1005 abc
1006-1010 xyz
In case column D is free to use (choose whichever column really if you want to) you could try:
Input:
Code:
Sub Test2()
Dim arr As Variant, x As Long, mx As Long, mn As Long, col As String
With ThisWorkbook.Sheets("Sheet1") 'Change accordingly
lr = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("B1:B" & lr).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=.Range("D1"), Unique:=True
arr = .Range("D2:D" & .Cells(.Rows.Count, "D").End(xlUp).Row).Value
For x = LBound(arr) To UBound(arr)
mn = .Evaluate("=MAX(IF(B2:B" & lr & "=""" & arr(x, 1) & """,A2:A" & lr & "))")
mx = .Evaluate("=MIN(IF(B2:B" & lr & "=""" & arr(x, 1) & """,A2:A" & lr & "))")
col = Split(.Cells(1, x).Address, "$")(1)
Debug.Print "Column " & col & " = " & mn & "-" & mx & " " & arr(x, 1)
Next x
.Range("D1:D" & .Cells(.Rows.Count, "D").End(xlUp).Row).Clear
End With
End Sub
Output:
On a very large dataset, I would suggest to use a Dictionary instead maybe (array formulas are not fast). But for a rather small dataset, I guess this is a fast way.
Swap the line:
Debug.Print "Column " & col & " = " & mn & "-" & mx & " " & arr(x, 1)
For:
.Cells(x + 1, 3).Value = "Column " & col & " = " & mn & "-" & mx & " " & arr(x, 1)
But you might want to play around with where and how you want to output your results.
For this method to work you need to add headers in the line above data.
Put this formula in a cell:
= "Column a = " & DMIN(A1:B11;A1;B1:B2) & " - " DMAX(A1:B11;A1;B1:B2)
syntax: DMIN( "the_whole_range_of_data_including_headers";" cell_with_header_in_column_with_search_values";" cell_with_header_and_cell_beneath_it_in_column_with_match_values")
I created a Sub for you that might help you.
Its maybe not perfect but with a little bit of tinkering it should work for what you want to achieve.
Please accept the answer and vote for it if it helps you.
Option Explicit
Public Sub Grouping()
Dim LastRow As Integer
Dim StartRow As Integer
Dim CurrentValue As String
Dim StartValue As String
Dim i As Integer
Dim k As Integer
Dim Outputstring As String
Dim LengthCounter As Integer
'2 -> insert Number of column B
LastRow = Worksheets("Sheet 1").Cells(Rows.Count, 2).End(xlUp).Row
StartValue = Worksheets("Sheet 1").Cells(1, 2).Value
StartRow = 0
LengthCounter = 0
k = 0
For i = 1 To LastRow
CurrentValue = Worksheets("Sheet 1").Cells(i, 2).Value
If CurrentValue = StartValue Then
LengthCounter = LengthCounter + 1
Else
Outputstring = Worksheets("Sheet 1").Cells(StartRow, 1).Value & " - " & Worksheets("Sheet 1").Cells(i - 1, 1).Value & " " & Worksheets("Sheet 1").Cells(i - 1, 2).Value
Worksheets("Sheet 1").Cells(k, 3).Value = Outputstring
k= k +1
StartRow = i
StartValue = Worksheets("Sheet 1").Cells(i, 2).Value
End If
Next i
End Sub

automatically updating vba concatenate column when changed

I'm concatenating 4 different formula based columns into one using VBA (to be able to change formatting while still concatenating). The concatenating VBA code works, but when the 4 individual columns update and pull the new information, the concatenated column doesn't change.
My concatenated code is this and it lies in column D or 4:
Sub joint1()
ActiveSheet.Range("a2", ActiveSheet.Range("a2").End(xlDown)).Select
Row = 2
Col = 4
For Each Cell In Selection
AE = Cells(Row, Col + 15)
Name = Cells(Row, Col + 9)
SC = Cells(Row, Col + 16)
PM = Cells(Row, Col + 10)
Cells(Row, Col) = Name & Chr(10) & "(" & AE & " - " & SC & ")" & Chr(10) & PM & " - PM"
With Cells(Row, Col)
.ClearFormats
.Characters(1, Len(Name)).Font.Bold = True
End With
Row = Row + 1
Next
End Sub
If you know how to add a feature to help my problem, I would be very appreciative!
Try this:
Option Explicit
Sub joint1()
Dim iRow As Long
Dim iCol As Long
Dim rng As Range
Dim rngSelect As Range
Dim Name As String
Set rngSelect = ActiveSheet.Range("a2", ActiveSheet.Range("a2").End(xlDown))
iRow = 2
iCol = 4
For Each rng In rngSelect
Name = Cells(iRow, iCol + 9)
Cells(iRow, Col) = "=M" & iRow & Chr(10) & " & ""("" & S" & iRow & " & "" - "" & T" & iRow & " & "")"" &" & Chr(10) & "N" & iRow & " & ""-PM"""
With Cells(iRow, iCol)
.ClearFormats
.Characters(1, Len(Name)).Font.Bold = True
End With
iRow = iRow + 1
Next
End Sub
This code creates a formula in each cell, rather than just copying the values.
The job could probably be done just as well with an excel formula. The formatting doesn't work with my version of excel (2007).

Resources