vba excel: how to copy characters from a cell to another - excel

I'm new in VBA world and I'm learning by your suggestions.
I've looked for several solutions, tried them but they were't ideal for my problem.
Here are the links
Find a string within a cell using VBA
How to Count the Number of a Specific Character in a Cell with Excel VBA
Which command in VBA can count the number of characters in a string variable?
What I need is the possibility to check the characters inInput and match with Match list key. After matched the string, copy the characters I in output.
As you can see, first rows are simple to match but in A8 cell (for example) there is a string with fourteen characters.
In this case I need that, when there is a string that begin with CMXXAB, the match is with WT (ALWAYS!).
The same thing happen when we have A12: it begins with ETRxxx and, after match will begin in output like JAZZ.

I think this will help you:
Option Explicit
Sub test()
Dim LastrowA As Long, i As Long, AppearA As Long, AppearB As Long
Dim strA As String, strB As String
With ThisWorkbook.Worksheets("Sheet1")
LastrowA = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 1 To LastrowA
strA = .Range("A" & i).Value
strB = .Range("C" & i).Value
'Check if strA appears in strB
AppearA = InStr(1, strB, strA)
If AppearA > 0 Then
.Range("B" & i).Value = strA
Exit For
End If
'Check if strB appears in strA
AppearB = InStr(1, strA, strB)
If AppearB > 0 Then
.Range("B" & i).Value = strB
Exit For
End If
Next i
End With
End Sub
Thank you so much for help.
after few days i've found solution for problem in my question.
infact, this is my solution and I hope to be good for helping anyone need something like this.
Sub AssociazioneRotabiliPerPivot()
Dim LastrowA, LastrowC As Long, i, j As Long, AppearA As Long, AppearB As Long
Dim strA As String, strB As String
With ThisWorkbook.Worksheets("sheet1")
LastrowA = .Cells(.Rows.count, "A").End(xlUp).Row
LastrowC = .Cells(.Rows.count, "C").End(xlUp).Row
For j = 1 To LastrowC
For i = 1 To LastrowA
strA = .Range("A" & i).Value
strB = .Range("C" & j).Value
AppearC = InStr(1, strA, strB)
If AppearB > 0 Then
.Range("B" & i).Value = strB
End If
If (InStr(1, strA, "CM") Or InStr(1, strA, "C4551R")) > 0 Then
.Range("B" & i).Value = "WT"
ElseIf InStr(1, strA, "ETR425") > 0 Then
.Range("B" & i).Value = "JAZZ"
End If
Next i
Next j
End With
End Sub

Related

Value of counter is not updating in a For Loop

I have data in B Column of an excel file. I have made a loop that If the value in B Cell is greater than a particular (len1) value, then the code puts the Cell (Value-Len1) value in a new cell at the end of the rows.
I increment the counter as lastrow = lastrow+1 everytime when the row is added. Now here is the problem. Iniitially in the input file I had 122 set of data. But by the time the For loop finishes the value of lastrow becomes 160, but the loop exits at 122. WHY?? Any Help will be appreciated.
For i = 1 To lastrow Step 1
If Range("B" & i).Value > len1 Then
Range("A" & lastrow + 1).Value = Range("A" & i).Value
Range("B" & lastrow + 1).Value = Range("B" & i).Value - len1
Range("B" & i).Value = len1
lastrow = lastrow + 1
End If
Next
To get the behaviour you want you need a while loop (or do loop)
i = 1
While i <= lastrow
If Range("B" & i).Value > len1 Then
lastrow = lastrow + 1
Range("A" & lastrow).Value = Range("A" & i).Value
Range("B" & lastrow).Value = Range("B" & i).Value - len1
Range("B" & i).Value = len1
End If
i = i + 1
Wend
I tested it with the sub below:
Sub LoopBeyondLastRow()
Dim i As Long, lastrow As Long, len1 As Long
len1 = 10
With ThisWorkbook.Sheets("Sheet1")
lastrow = .Cells(Rows.Count, "B").End(xlUp).Row
i = 1
While i <= lastrow
If .Range("B" & i).Value > len1 Then
lastrow = lastrow + 1
.Range("A" & lastrow).Value = .Range("A" & i).Value
.Range("B" & lastrow).Value = .Range("B" & i).Value - len1
.Range("B" & i).Value = len1
End If
i = i + 1
Wend
End With
End Sub
Please note the following:
Inside the loop I incremented lastrow first and then used it in the following 2 statements (to reduce the number of addition operations)
In my test code I added With ThisWorkbook.Sheets("Sheet1") to fully qualify all ranges. Not doing this is the source of many bugs that are sometimes very difficult to pinpoint. One should get in the habbit of never to write Range or Cells without a little . before them.
A faster method would be to export the range values to array and then do the comparision. Store the final output into a temp array and write it back to the worksheet.
If you want to follow your approach then is this what you are trying? I have commented the code so you should not have a problem understanding it. Basically you need 2 loops if you want to recheck the data that you are adding at the end of the row.
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim ComparisionValue As Long
Dim countOfMatchedValues As Long
Dim lRow As Long
Dim i As Long
Dim outputRow As Long
Dim rng As Range
'~~> Change this to the relevant sheet
Set ws = Sheet1
'~~> Change this to the relevant
'~~> comparision value
ComparisionValue = 122
With ws
'~~> Start an indefinite loop
Do
'~~> Find last row
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Fix the output row for the new data
outputRow = lRow + 1
'~~> Check if there are any matches for your condition
countOfMatchedValues = Application.WorksheetFunction.CountIf( _
.Range("B1:B" & lRow), ">" & ComparisionValue)
'~~> If not then exit loop
If countOfMatchedValues = 0 Then Exit Do
'~~> Do your stuff
For i = 1 To lRow
If .Range("B" & i).Value > ComparisionValue Then
.Range("A" & outputRow).Value = .Range("A" & i).Value
.Range("B" & outputRow).Value = .Range("B" & i).Value - ComparisionValue
.Range("B" & i).Value = ComparisionValue
outputRow = outputRow + 1
End If
Next i
Loop
End With
End Sub
In Action
for loops use a pre-defined number of iterations. For an unknown number of iterations you need to use a while loop.
Your code uses the value of lastRow at the time it was interpreted, and is never updated again.
This is similar to:
lastRow = 1
Debug.Print lastRow
lastRow = lastRow + 1
Debug.Print lastRow
You will see:
1
2
and not:
2
2
because once the first Debug statement has been executed, changing the value of lastRow doesn't affect this particular output anymore.
Test the next code, please:
Sub TestLoopAddedRowsInclusive()
'..... your code defining LastRow and len1
Dim lastRInit As Long
lastRInit = LastRow
For i = 1 To Rows.count
If Range("B" & i).Value = "" And i >= lastRInit Then Exit For
If Range("B" & i).Value > len1 Then
Range("A" & LastRow + 1).Value = Range("A" & i).Value
Range("B" & LastRow + 1).Value = Range("B" & i).Value - len1
Range("B" & i).Value = len1
LastRow = LastRow + 1
End If
Next
End Sub

Excel formula that concatenate the time

Apologies for the inconvenience here is the updated screenshot of what the input and expected result needed. Thank you!
This may help you:
VBA Method:
Option Explicit
Sub TEST()
Dim LastRowA As Long, LastRowD As Long, i As Long, j As Long
Dim Name As String, StartingTime As String, EndingTime As String
j = 0
With ThisWorkbook.Worksheets("Sheet1")
LastRowA = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 1 To LastRowA
If i >= j Then
StartingTime = .Range("A" & i).Value
Name = .Range("B" & i).Value
For j = i + 1 To LastRowA + 1
If .Range("B" & j).Value <> Name Then
EndingTime = .Range("A" & j - 1).Value
LastRowD = .Cells(.Rows.Count, "D").End(xlUp).Row
.Range("D" & LastRowD + 1).Value = Name
If StartingTime = EndingTime Then
.Range("E" & LastRowD + 1).Value = StartingTime
Else
.Range("E" & LastRowD + 1).Value = StartingTime & "-" & EndingTime
End If
Exit For
End If
Next j
End If
Next i
End With
End Sub
Results:
Excel Method:
Import and drag down the below formulas
Formula in cell D2:=LOOKUP(2,1/(COUNTIF($D$1:D1,$B$1:$B$8)=0),$B$1:$B$8)
Formula in cell E2:=IF(INDEX($A$1:$A$8,MATCH(D2,$B$1:$B$8,0))= LOOKUP(2,1/($B$1:$B$8=D2),$A$1:$A$8),LOOKUP(2,1/($B$1:$B$8=D2),$A$1:$A$8),INDEX($A$1:$A$8,MATCH(D2,$B$1:$B$8,0)) & "-" & LOOKUP(2,1/($B$1:$B$8=D2),$A$1:$A$8))
Results:

How cut a substring?

I have a lot of string which can contain italic font. I want to copy this string with this font. In each new string I have bold word
Example:
BIG STRING:
I tried:
Public Function GetDefinition(ByVal rngText As Range) As String
Dim theCell As Range
Set theCell = rngText.Cells(1, 1)
For I = 1 To Len(theCell.Value)
If theCell.Characters(I, 1).Font.Bold = False Then
If theCell.Characters(I + 1, 1).Text = " " Then
theChar = theCell.Characters(I, 1).Text
Else
theChar = theCell.Characters(I, 1).Text
End If
Results = Results & theChar
End If
Next I
GetDefinition = Results
End Function
I think you could use this:
Option Explicit
Sub test()
Dim LastRow As Long, i As Long, j As Long, PositionOfDot As Long
With ThisWorkbook.Worksheets("Sheet1")
'Find last row of column A
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
'Loop from row 1 to lastrow
For i = 1 To LastRow
'Copy paste from column A to C keeping formatting
.Range("A" & i).Copy .Range("C" & i)
'Find the position of "."
PositionOfDot = InStr(1, .Range("A" & i), ".")
'Delete characters starting from the first one up to PositionOfDot+1
.Range("C" & i).Characters(1, PositionOfDot + 1).Delete
Next i
End With
End Sub
Results:
If your bold string always ends with a dot this will do it for you:
Option Explicit
Public Function GetDefinition(ByVal rngText As Range) As String
Dim SplitBold As Variant
SplitBold = Split(rngText, ". ")
GetDefinition = Trim(SplitBold(1))
End Function

How to check for duplicate on specific column?

Im trying to detect duplicates on column("G") of my input workbook and by using lastrow of its data at column("E") to merge upwards by using & "" & after which it will delete the entireRow and this process continue until there are no more duplicates.
I tried and also look up for many codes including delete and duplicates but I am still having trouble.
Dim myCell As Range, myRow As Integer, myRange As Range, myCol As Integer, X As Integer
'Count number column
Set wsInput = Workbooks("InputB.xls").Worksheets("HC_MODULAR_BOARD_20180112")
myCol = Range(Cells(3, 7), Cells(3, 7).End(xlDown)).Count
'Loop each column to check duplicate values & highlight them.
For X = 3 To myRow
Set myRange = Range(Cells(2, X), Cells(myRow, X))
For Each myCell In myRange
If Workbooks("InputB.xls").Worksheets("HC_MODULAR_BOARD_20180112").CountIf(myRange, myCell.Value) > 1 Then
myCell.Interior.ColorIndex = 3
End If
Next
Next
' allow values at Column"E" to merge upwards and delete all duplicate and its row (missing)
I have no clue how to delete after copying data on top of the column. Someone please help.
Many Thanks,
Adrian
You could try:
Option Explicit
Sub test()
Dim LastRow As Long, i As Long, y As Long, Counter As Long
Dim SearchValue As String, AddValue As String
With ThisWorkbook.Worksheets("Sheet1") ' Always select your worksheet name
LastRow = .Cells(.Rows.Count, "C").End(xlUp).Row
Counter = 0
AddValue = ""
SearchValue = ""
For i = LastRow To 3 Step -1
SearchValue = .Range("C" & i).Value
If SearchValue <> "" Then
If Application.WorksheetFunction.CountIf(.Range("C3:C" & LastRow), SearchValue) > 1 Then
For y = i To 3 Step -1
If .Range("C" & y).Value = SearchValue Then
If AddValue = "" Then
AddValue = .Range("E" & y).Value
Else
AddValue = AddValue & ", " & .Range("E" & y).Value
.Rows(y).EntireRow.Delete
Counter = Counter + 1
End If
End If
Next y
.Range("E" & i - Counter).Value = AddValue
AddValue = ""
SearchValue = ""
Counter = 0
End If
End If
Next i
End With
End Sub

Merge rows into one based on full stop

I have a table in the following format.
all that is
well known for
let be apples.
abs kdjhkj kfhksh sh
kjsfhkshgkh dh.
I want the rows to merge based on the fullstop, whenever a full stop comes, a new row should be created untill next full stop occurs.
example
all that is well known for let be apples.
abs kdjhkj kfhksh sh kjsfhkshgkh dh.
I see we can merge by n number of rows into one using inbuild tools. But I have a huge list, I cannot go around and do that for each set.
Any solution, in code or through excel or libreoffice calc will be helpful.
though I can try macro but not preferring that. Anyways if that is the only way to achieve it then why not.
I think there is no way to archive this with excel function. i try to create a code fulfill your needs:
Code:
Option Explicit
Sub test()
Dim str As String
Dim i As Long, LastRowA As Long, LastRowC As Long
With ThisWorkbook.Worksheets("Sheet1")
LastRowA = .Cells(.Rows.Count, "A").End(xlUp).Row
For i = 1 To LastRowA
If InStr(1, .Range("A" & i).Value, ".") > 0 Then
If str = "" Then
str = .Range("A" & i).Value
Else
str = str & " " & .Range("A" & i).Value
End If
LastRowC = .Cells(.Rows.Count, "C").End(xlUp).Row
If LastRowC = 1 And .Range("C1").Value = "" Then
.Range("C" & LastRowC).Value = str
Else
.Range("C" & LastRowC + 1).Value = str
End If
str = ""
Else
If str = "" Then
str = .Range("A" & i).Value
Else
str = str & " " & .Range("A" & i).Value
End If
End If
Next i
End With
End Sub
Results:
If you just import it in a google drive you can do it with:
=SPLIT(CONCATENATE(A1:A5);".")
You can do it in excel by using concatenate in the same way and then also separating by "." but I do not think you can't split in that way to my knowledge. In any case, in VBA is not a difficult code. But I guess you just want to solve this and you are doing it in excel beceause you don't know how to do it in any other way.
The below code is effective compare to first answer.
Sub Program1()
Dim wb As Workbook
Dim ws As Worksheet
Dim Lastrow As Long
Dim Str1 As String
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet1")
Lastrow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
j = 1
For i = 1 To Lastrow
If InStr(1, ws.Cells(i, 1).Value, ".") > 0 Then
ws.Cells(j, 3).Value = Str1 & ws.Cells(i, 1).Value
j = j + 1
Str1 = ""
Else
Str1 = Str1 & ws.Cells(i, 1).Value
End If
Next
End Sub

Resources