I have an excel table that contain values in these formats. The tables span over 30000 entries.
I need to clean this data so that only the numbers directly after V- are left. This would mean that when the value is SV-51140r3_rule, V-4407..., I would only want 4407 to remain and when the value is SV-245744r822811_rule, I would only want 245744 to remain. I have about 10 formulas that can handle these variations, but it requires a lot of manual labor. I've also used the text to column feature of excel to clean this data as well, but it takes about 30 minutes to an hour to go through the whole document. I'm looking for ways that I can streamline this process so that one formula or function can handle all of these different variations. I'm open to using VBA but don't have a whole lot of experience with it and I am unable to use Pandas or any IDE or programming language. Help please!!
I've used text to columns to clean data that way and I've used a variation of this formula
=IFERROR(RIGHT(A631,LEN(A631)-FIND("#",SUBSTITUTE(A631,"-","#",LEN(A631)-LEN(SUBSTITUTE(A631,"-",""))))),A631)
Depending on your version of Excel, either of these should work. If you have the ability to use the Let function, it will improve your performance, as this outstanding article articulates.
If you're on a really old version of excel, you'll need to hit ctl shift enter to make array formula work.
While these look daunting, all these functions are doing is finding the last V (by this function) =SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π","") and then looping through each character and only returning numbers.
Obviously the mushroom π could be any character that one would consider improbable to appear in the actual data.
Old School
=TEXTJOIN("",TRUE,IF(ISNUMBER(MID(MID(SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π",""),
FIND("-",SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π","")),9^9),
FILTER(COLUMN($1:$1),COLUMN($1:$1)<=LEN(MID(SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π",""),
FIND("-",SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π","")),9^9))),1)+0),
MID(MID(SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π",""),
FIND("-",SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π","")),9^9),
FILTER(COLUMN($1:$1),COLUMN($1:$1)<=LEN(MID(SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π",""),
FIND("-",SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π","")),9^9))),1),""))
Let Function
(use this if you can)
=LET(zText,SUBSTITUTE(RIGHT(SUBSTITUTE(A2,"V",REPT("π",999)),999),"π",""),
TEXTJOIN("",TRUE,IF(ISNUMBER(MID(MID(zText,FIND("-",zText),9^9),
FILTER(COLUMN($1:$1),COLUMN($1:$1)<=LEN(MID(zText,FIND("-",zText),9^9))),1)+0),
MID(MID(zText,FIND("-",zText),9^9),
FILTER(COLUMN($1:$1),COLUMN($1:$1)<=LEN(MID(zText,FIND("-",zText),9^9))),1),"")))
VBA Custom Function
You could also use a VBA custom function to accomplish what you want.
Function getNumbersAfterCharcter(aCell As Range, aCharacter As String) As String
Const errorValue = "#NoValuesInText"
Dim i As Long, theValue As String
For i = Len(aCell.Value) To 1 Step -1
theValue = Mid(aCell.Value, i, 1)
If IsNumeric(theValue) Then
getNumbersAfterCharcter = Mid(aCell.Value, i, 1) & getNumbersAfterCharcter
ElseIf theValue = aCharacter Then
Exit Function
End If
Next i
If getNumbersAfterCharcter = "" Then getNumbersAfterCharcter = errorValue
End Function
So at the moment I have a working code to get multiple items in a cell following a condition
My code is:
=Contatenate(
IF('Sheet1'!E3 = "R",'sheet1'!A3,""), " ",
IF('Sheet1'!E4 = "R",'sheet1'!A4,""), " ",
and so on.....
it then returns every name that meets this condition.
I was just wondering if there was a quicker way to do this.
Thanks!
Leaving the solution as an answer to make it more clear:
=ArrayFormula(TEXTJOIN(" ",TRUE,IF('Contact & Overview'!E103:E122="R",'Contact & Overview'!A103:A122,"")))
From Sheets TEXTJOIN:
Sample Usage
TEXTJOIN(β β, TRUE, βhelloβ, βworldβ)
TEXTJOIN(β, β, FALSE, A1:A5)
Syntax
TEXTJOIN(delimiter, ignore_empty, text1, [text2, ...])
I have a list box that I'm trying to populate in an application to contain Excel tab names or Access tables. It's created by a simple schema grab:
dtSheet = OpenCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
It then gets put into a simple list (of String):
For Each Row In dtSheet.Rows
ListOfSheets.Add(Row("TABLE_NAME").ToString())
Next
This works fine if I open up an Access database, the names of the tables are listed nicely. However, when I use it for Excel, I get symbols such as $ and quotes "'". I'd like to trim this off to just have the tab names but so far I haven't been able to find anything to help my issue specifically.
My suspicion is that the answer is in the {Nothing...."TABLE"} object. I'm a little light on how filters like this work and I was having issues wrapping my head around it after reading the .NET documentation.
Another idea would be to do some post string alteration trimming but I'd like to see if there was an easier way to get the simple string name that I want from the start.
Any help would be appreciated.
Based on the discussion from jmcihinney, I built a slightly better code.
dtSheet = OpenCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
dtSheet.Columns.Add("Table_Text", Type.GetType("System.String"))
For i As Integer = dtSheet.Rows.Count - 1 To 0 Step -1
If Microsoft.VisualBasic.Strings.Right(dtSheet.Rows(i)("TABLE_NAME"), 1) <> "$" Then
dtSheet.Rows.RemoveAt(i)
Else
dtSheet.Rows(i)("TABLE_Text") = Replace(dtSheet.Rows(i)("TABLE_NAME"), "$", "")
End If
Next
I essentially add a column to the datatable that is built from the list pull. To remove anything that isn't a table (e.g. named ranges, Sheet views) I check the Table_Name column for the suffix of "$". Note I go backwards to keep from messing with any indexing.
Then in the Else statement I put a "Replace" to make the table_text a "$"less version of Table_Name
That way I can then build my listbox like this:
Me.lbTableList.DataSource = dtsheet
Me.lbTableList.DisplayMember = "TABLE_Text"
Me.lbTableList.ValueMember = "TABLE_NAME"
This makes my table look nice regardless if I loaded an Access database or Excel file. This also allows me to just pass the TABLE_NAME to the connection command and not worry whether there is a "$" in the name or not:
DBCmd.CommandText = "SELECT * FROM [" & strTable & "]"
I programmed a communication tool for the production floor. This tool will register what they have done, who has done it and on what time.
The following should check whether the textbox value equals the value in the worksheet or if the textbox (textbox is TextTools1) is empty. If this is true, then nothing should happen and the thus the value of the textbox is gonna stay the same.
If the textbox is not empty or is not equal to what has been previously saved in the worksheet (thus the value has changed), then it should be registered which operator has done it and what date and what time.
It works when the textbox is empty, but when the value of the textbox has stayed the same (thus TextTools.value=ActiveCell.Offset(0,23).value (Correct)) it still adds the operators name, date and time.
Something is going wrong when trying to compare the textbox value and the cell value, but cant put my finger on it.
Sheets("Checklist & overdracht").Visible = True
Sheets("Checklist & overdracht").Select
If TextTools1.Value = Range("AZ1").Value Or TextTools1.Value = Empty Then
Sheets("Checklist & overdracht").Select
rowloc1.Value = ActiveCell.Row
ActiveCell.Offset(0, 23).Value = TextTools1.Value
Else
Sheets("Checklist & overdracht").Select
rowloc1.Value = ActiveCell.Row
ActiveCell.Offset(0, 23).Value = TextTools1.Value & " " & "(" & cboOperator.Value & " " & Format(DateValue(CStr(Now)), "short date") & " " & Format(TimeValue(CStr(Now)), "hh:mm") & ")"
End If
Edit; changed it to the code above. I tested this in another userform (and used f8) and it works brilliantly, but when I put in the userform that will actually run this code, than it doesnt have the same result...
Edit2; So apparently something goes wrong with Range(AZ1).Value reference. Because when I enter a random value instead of the range and then run the code, it does work. Is there a different way of referencing?
Ok based on your comments
Stop using active cell when code from a user form is communicating to the compiler what sheet is what. You need to fully qualify what sheet you are using. Im not entirely sure where in the code the active sheet is being set but I am fairly certain the answer is never. Another reason selecting and referencing .ActiveWhatever is bad is a cardinal sin of vba is interacting with the actual application object instead of doing everything in memory. It bogs everything done and performance suffers considerably. When you start writing pretty dense stuff then you will inevitably suffer from issues where the compiler gets confused as to what thing it should be looking at and you'll have a grand ol' time of troubleshooting that nonsense.
Also, it might be a good idea to check for more than just "=Empty". What if there is a null or empty string? I tend to check for:
.value = "" OR ISNULL(.Value)=True OR .Value = vbNullstring
this isnt real feedback though - tons of people have different ways of doing the same thing.
Try:
Thisworkbook.Sheets("YOURSHEETNAME").Range("YOURRANGE").Offset(0,23).Value = Someothervalue.
Let me know if youre still facing issues.
I am very new to VB macro.In sheet 3 i have three columns named "Country " "Provinces" and "Risk"
For "Provinces", values present are NB,NS,NF,PE. IN sheet5, i have written a code like
`(val) Like "*[HH,HHJ,qqw,www]" Then
to check if user has provided input like NB or like NB, NS or like PE only then corresponding values from Risk will get displayed. Now with the above code , if user is entering value as "," also results is getting displayed as , is present in the Like statement.
Kindly guide me.
You can't use VBA Like that way. Try:
X = "abc, NB"
If X Like "*NB" Or _
X Like "*NS" Or _
X Like "*NF" Or _
X Like "*PE" Then
Debug.Print "X is in the Maritimes"
End If
If you set Option Compare Text at the beginning of your macro, you don't have to Ucase the string being tested.
For complex comparisons, you can use Regular Expressions in VBA. You need to set the appropriate reference.