I have strings stored in cells of a column in Excel that I would like to concatenate in several pieces, like sentences, with VBA. Here is an example:
Column A
Jack
learns
VBA
Jack
sits
on
a
couch
Jack
wants
chocolate
cake
I finally found a way to concatenate all strings and save the sentences to a cell:
Sub JACK()
Dim MP() As String
Dim Str As String
Dim i As Integer
For i = 2 To 10
ReDim Preserve MP(i)
MP(i) = Cells(i, 1).Value
Next i
Str = Join(MP)
Cells(1, 2).Value = Str
End Sub
But I would like to have the sentences that start with "Jack" and end with the row "Jack - 1", each saved in seperate cells.
Could anyone help me???
Thank you so much!
This is the code snippet that will do what you want:
Sub test_func()
' this is the starting cell (keep in mind that the first word in the cell is 'Jack' so the start cell is actually starting at C2)
Dim startCell As range
Set startCell = ThisWorkbook.ActiveSheet.range("B2")
' reading all the cells in the range
Dim wordRange As range
Set wordRange = ThisWorkbook.ActiveSheet.range("A2:A13")
' creating two variables row and col
Dim row As Long
Dim col As Long
' for each word in wordRange
Dim word As Variant
For Each word In wordRange
' as soon as we find the word 'Jack'
If word.Value = "Jack" Then
' move the cursor to row 0
row = 0
' move the cursor one cell to the right
col = col + 1
End If
' else if the word is not 'Jack', put the word on the cursor cell
startCell.Offset(row, col) = word
' then move the cursor one cell down
row = row + 1
Next
End Sub
The function is:
reading all the words from the column A into a range.
dumping the elements from the range (word) starting on B2, one by one
as soon as it finds the word 'Jack', it will start at row 0, move to the right and continue
The outcome looks like this:
This is the output of the script
Note that the words are starting on C2 even though you chose B2 to be the starting cell; this is because the first word in the list is 'Jack', so it is moving one cell to the right as soon as it starts.
EDIT:
Here might be the function that you are looking for:
Sub test_func()
' this is the starting cell (keep in mind that the first word in the cell is 'Jack' so the start cell is actually starting at C2)
Dim startCell As range
Set startCell = ThisWorkbook.ActiveSheet.range("B2")
' reading all the cells in the range
Dim wordRange As range
Set wordRange = ThisWorkbook.ActiveSheet.range("A2:A13")
' creating two variables row and col
Dim row As Long
Dim col As Long
' string that holds each sentence
Dim sentence As String
' for each word in wordRange
Dim word As Variant
For Each word In wordRange
' as soon as we find the word 'Jack' and the sentence is not empty, the sentence is complete
If word.Value = "Jack" And sentence <> "" Then
'printing out the whole sentence
startCell.Offset(row, col) = sentence
' emptying the sentence when 'Jack' is found
sentence = ""
' move the cursor one cell down
row = row + 1
End If
' else if the word is not 'Jack', concatenates the word into the sentence
sentence = sentence & " " & word
Next
' adding this again at the end of the loop because the last sentence is not outputted otherwise
startCell.Offset(row, col) = sentence
End Sub
This function differs from the previous one because it concatenates the words into a sentence before dumping it out. In this function, the start cell is correct and is not moving down or right when the program starts. This is because we can check whether the sentence that it is about to dump out is empty or not, if it is; then it means we did not finish our sentence.
Hope this helps!
This is the result screenshot of the second version of the code
Extract Sentences From Column
Sub JACK()
Const JackStart As String = "Jack"
Const JackEnd As String = "."
Const Delimiter As String = " "
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim slCell As Range: Set slCell = ws.Cells(ws.Rows.Count, "A").End(xlUp)
Dim srg As Range: Set srg = ws.Range("A2", slCell)
Dim dCell As Range: Set dCell = ws.Range("B2")
Dim sCell As Range
Dim JackString As String
Dim FoundFirst As Boolean
For Each sCell In srg.Cells
If sCell.Value = JackStart Then
If FoundFirst Then
dCell.Value = JackString & JackEnd
Set dCell = dCell.Offset(1) ' next row
Else
FoundFirst = True
End If
JackString = JackStart
Else
If FoundFirst Then JackString = JackString & Delimiter & sCell.Value
End If
Next sCell
dCell.Value = JackString & JackEnd
MsgBox "Jacks extracted.", vbInformation
End Sub
Related
I am struggling with searching for a string in column and then filling a unique text in the adjacent cell.
For example, I have 3 names and I want to tweak them in adjacent cells as shown below (in reality I have around 20):
A
B
1
name
Desired Format
2
Cat
3
Dog
4
Elephant
The idea is to look for cat in range (A2:A4) and if found, input "17.Catiscool" in the adjacent cell and similarly look for Dog and if found, input "13.Dogisgood" in the adjacent cell to dog.
So far I have this code which just inputs "13.Dogisgood" in B3:
Sub To_be_renamed_as()
'Writing this to determine Correct Name format based on what we have from A3:A25
Dim oldRange As Range
Dim newRange As Range
Dim oldname As Object
Dim newname As String
'Our names start from A3 so I am going to start the range from A3
Set oldReportrange = Range("A3:A25")
Set newReportrange = Range("B3:B25")
For Each oldname In oldRange
If oldname Like "dog" Then
End If
newname = ("13.dogisgood")
oldname.Offset(0, 1) = newname
Next oldname
End Sub
In this instance, it feels like a Select ... Case statement would work best. I've edited your code to show one in use
Sub To_be_renamed_as()
'Writing this to determine Correct Name format based on what we have from A3:A25
Dim oldRange As Range
Dim newRange As Range
Dim oldname As Object
Dim newname As String
'Our names start from A3 so I am going to start the range from A3
Set oldReportrange = Range("A3:A25")
Set newReportrange = Range("B3:B25")
For Each oldname In oldRange
Select Case ucase(oldname.value) 'Make the input value all uppercase for easier comparison
case "DOG"
newname = "13.dogisgood"
case "CAT"
newname = "17.Catiscool"
case else
newname = ""
end select
oldname.Offset(0, 1) = newname
Next oldname
End Sub
Please, try the next code. It should be very fast, even for big ranges, using arrays:
Sub To_be_renamed_as()
Dim sh As Worksheet, arrRep, El, arrEl, rng As Range, arrRng, i As Long
Set sh = ActiveSheet 'use here the sheet you need
arrRep = Split("cat|17.Catiscool,dog|13.Dogisgood,elephant|ElephantIsBig", ",") 'place here your conditions separated by "|"
Set rng = sh.Range("A3:B25"): arrRng = rng.value 'set the range and put it in an array
For Each El In arrRep 'iterate between the arrRep elements
arrEl = Split(El, "|") 'split each element by "|"
For i = 1 To UBound(arrRng) 'iterate between the arrRng rows
If arrRng(i, 1) Like arrEl(0) Then arrRng(i, 2) = arrEl(1) 'when in the first column the search element is found
Next i 'the conditional string is passed in the second array column
Next
rng.value = arrRng 'Drop the processed array into the range, at once
End Sub
You can add in arrRep as many conditions (separated by "|") as you need...
Please, test it and send some feedback.
Dear stack overflow community:
To be brief, the goal of this program is to allow user to input text in Cell C53 and for the program to find matching text in a string in contained in each row within Column A, then return the text in column B on the same row if found (otherwise, return "Use your best judgement".)
I've successfully created the VBA code to find a matching text in a specific row in Column A and return the value in the same row in column B. However, it only works on one row hardcoded into the code. I need to adjust it to loop through a range of rows in column A because there may be matching text in other rows.
My code currently looks like this:
Sub Test_2()
Dim SearchString, SearchText
SearchKey = Range("A1")
SearchNote = Range("C53")
If InStr(SearchNote, SearchKey) > 0 Then
Range("C59").Value = Range("B1").Value
Else
Range("C59").Value = "Please use your best judgement."
End If
End Sub
Hence, if A1 contains "limit", and I type into C53 "client wants to upgrade limit", it will return to C59 the text in B1 because it was found.
The only addition I have been trying to make is nesting what I currently have into a loop to check other rows in Column A. For example, if A1 was "cheque" and A2 was "limit", my current code would only check A1 and not find a match resulting in the prompt "Please use your best judgement." It should be able to check A1, A2, A3 ... A50 ...
I've been having difficulties translating this to code in VBA, and was hoping for some assistance.
Find Word in Sentence
The 1st code goes into a standard module e.g. Module1. Only run the 1st procedure which is calling the 2nd procedure when needed.
Adjust the constants as you see fit. If this is used in one worksheet only then you have to change srcName and tgtName to the same string.
To automate this, copy the second short code to the sheet module (e.g. Sheet1) worksheet where the Answer and Question Cells are. Then you run nothing, it's automatic.
Standard Module e.g. Module1
Option Explicit
Public Const queCell As String = "C53" ' Question Cell
Sub writeAnswer()
' Data
Const srcName As String = "Sheet1" ' Source Worksheet Name
Const srcFirstRow As Long = 1 ' Source First Row Number
Const srcLastRowCol As String = "A" ' Source Last Row Column ID
Dim Cols As Variant: Cols = Array("A", "B") ' Source Column IDs
' Target
Const tgtName As String = "Sheet1" ' Target Worksheet Name
Const ansCell As String = "C59" ' Answer Cell
' Other
Const msg As String = "Please use your best judgement." ' Not Found Message
Dim wb As Workbook: Set wb = ThisWorkbook ' The workbook with this code.
' Define column range.
Dim src As Worksheet: Set src = wb.Worksheets(srcName)
Dim rng As Range
Set rng = src.Columns(srcLastRowCol).Find("*", , xlValues, , , xlPrevious)
If rng Is Nothing Then Exit Sub
If rng.Row < srcFirstRow Then Exit Sub
Set rng = src.Range(src.Cells(srcFirstRow, srcLastRowCol), rng)
' Write values from column range to jagged array (Data(0) & Data(1)).
Dim ubc As Long: ubc = UBound(Cols)
Dim Data As Variant: ReDim Data(ubc)
Dim j As Long
For j = 0 To ubc
getRange(Data(j), rng.Offset(, src.Columns(Cols(j)).Column _
- src.Columns(srcLastRowCol).Column))
If IsEmpty(Data) Then Exit Sub
Next
' Search Data(0) Array for string contained in Question Cell
' and write result from Data(1) Array to Answer Cell.
Dim tgt As Worksheet: Set tgt = wb.Worksheets(tgtName)
Dim Sentence As String: Sentence = tgt.Range(queCell).Value
Dim i As Long
For i = 1 To UBound(Data(0))
If Sentence = "" Then Exit For
If Trim(Data(0)(i, 1)) <> "" Then
If InStr(1, Sentence, Trim(Data(0)(i, 1)), vbTextCompare) > 0 Then
tgt.Range(ansCell).Value = Data(1)(i, 1)
Exit Sub
End If
End If
Next i
' If string not found, write Not Found Message to Answer Cell.
tgt.Range(ansCell).Value = msg
End Sub
' Writes the values of a range to a 2D one-based array.
Sub getRange(ByRef Data As Variant, DataRange As Range)
Data = Empty
If DataRange Is Nothing Then Exit Sub
If DataRange.Rows.Count > 1 Or DataRange.Columns.Count > 1 Then
Data = DataRange.Value
Else
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = DataRange.Value
End If
End Sub
Sheet Module e.g. Sheet1
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Me.Range(queCell), Target) Is Nothing Then
writeAnswer
End If
End Sub
I'm still new to VBA and couldn't find any solution using the search-function so far.
Problem:
I have (in this case ten sheets) a row with over 500 cells containing strings with 5-7 words.
Now I need to delete all columns where the searched word is not the last word,but the word is in all cells (in the row) at different positions in the string.
I tried this:
Dim examinee As Variant
Dim cell As Range
Dim word As String
Dim myCell As String
examinee = InputBox("How many sheets?")
word = InputBox("Looking for?")
For A = 1 To examinee
Sheets("sheet" & A).Select
On Error Resume Next
Range("A3", Range("A3").End(xlToRight)).Select
For Each Cell In Selection.Cells
myCell = Right(Cell, Len(Cell) - (InStrRev(Cell, " ") - 1))
MsgBox myCell ' just to be sure the word is found
If myCell Like word Then
Selection.Cells.Bold = False
Else
Delete.Column
End If
Next Cell
Next
I can find&identify the word and "If" works fine so far, just nothing happens to the selected cell and the column wasn't deleted.
With some changes I can only delete the entire row but it isn't what I need.
Any help appriciated.
Thx in advance.
This should work, but I'd recommend cleaning up the syntax. I've removed the code where you're selecting ranges (there's lots of info online about why you shouldn't do this).
An array is created to find the last word and that's tested against the search value.
Sub Test()
Dim examinee As Variant
Dim cell As Range
Dim word As String
Dim myCell As String
Dim arr() As String
Dim strLastWord As String
'How Many Sheets Should We Loop?
examinee = InputBox("How many sheets?")
'What Word Are We Searching For?
word = InputBox("Looking for?")
'Loop Sheets
For A = 1 To examinee
'Loop Cells In Row 3
For Each cell In Range("A3", Range("A3").End(xlToRight))
'Get The Value Of The Current Cell
myCell = Right(cell, Len(cell) - (InStrRev(cell, " ") - 1))
'Is It A Single Word?
If InStr(1, myCell, " ") Then
'Several Words. Create An Array Of Individual Words In The Cell
arr() = Split(myCell, " ")
'Get The Number Of The Last Word
strLastWord = arr(UBound(arr))
Else
'Single Word. Get The Word
strLastWord = myCell
End If
'Is The Last Word = The Search Word?
If strLastWord = word Then
'Yes. Make It Bold
cell.Font.Bold = True
Else
'No. Delete The Column
Columns(cell.Column).Delete
End If
Next cell
Next
End Sub
I think this will help you
Sub findtext()
Dim wsAkt As Worksheet
Dim i As Integer
Dim k As Integer
Dim x As Integer
Dim strWord As String
Dim intWord As Integer
'get the word
strWord = Application.InputBox("Looking for?")
'length of word
intWord = Len(strWord)
'loop through all worksheets
For i = 1 To ThisWorkbook.Worksheets.Count
'variable for selected worksheet
Set wsAkt = ThisWorkbook.Worksheets(i)
'get how many columns are in row 3
x = wsAkt.Cells(3, wsAkt.Columns.Count).End(xlToLeft).Column
'loop through row 3 columns
For k = 1 To x
'if last Word in cell = the word then it has to have the same length
If Right(wsAkt.Cells(3, k), intWord) <> strWord Then
'delete selected column
wsAkt.Columns(k).Delete
End If
Next k
Next i
End Sub
(Its not tested)
I have two sheets say (Sheet1)=Sheets("Jan") and sheet2=Sheets("Feb")
I want to copy only that data from range b5:b81 from sheets ("Jan") to sheets("Feb") if it meets the condition in range AN5:AN81.
I am using this code but not working
Sub CopyRows()
Dim Rng As Range
Dim Rng2 As Range
Dim Cl As Range
Dim str As String
Dim RowUpdCrnt As Long
Set Rng = Sheets("Jan").UsedRange 'the range to search ie the used range
Set Rng2 = Sheets("Jan").Range("B")
str = "WRK." 'string to look for
Sheets("Feb").Range("B5:B81").Value = ""
RowUpdCrnt = 5
' In my test data, the "Yes"s are in column AN. This For-Each only selects column AN.
' I assume all your "Yes"s are in a single column. Replace "B" by the appropriate
' column letter for your data.
For Each Cl In Rng.Columns("AN").Rows
If Cl.Text = str Then
'if the cell contains the correct value copy it to next empty row on sheet 2 & delete the row
Cl.cell(2, 5).Copy Sheets("Feb").Cells(RowUpdCrnt, 1)
RowUpdCrnt = RowUpdCrnt + 1
End If
Next Cl
End Sub
In my Excel sheet, I have VBA code to detect the last non-empty cell in Column A and add incremental serial number value in that cell (in below example cell A6 value should be SN104).
This processing is limited only to Column A, and in this image example first non-empty last cell is at A6, sometimes it can be after 100 cells or 1000 cells.
Is there any simple way to handle this scenario?
Public Function GetLastCell(ByVal startRng as Range) as Range
With startRng
Set GetLastCell = IIf(.Offset(1).Value = "", .Offset(0), .End(xlDown))
End With
End Function
For your example, you can define a Range variable rng, and call the above function in this way:
Dim rng as Range
Set rng = GetLastCell( Range("A1") )
Then rng is referring to the last cell of Column A
Something like
Dim lngLastUsedRow as Integer
lngLastUsedRow = Range("A65536").End(xlUp).Row
Dim lngFirstEmptyRow as Integer
lngFirstEmptyRow = Range("A65536").End(xlUp).Offset(1,0)
// do your increment
newValue = Cint(Mid(CurrentWorkSheet.Range("A" + lngLastUsedRow).Value,2)) + 1
CurrentWorkSheet.Range("A" & lngFirstEmptyRow).Value = "SN" + newValue
I don't have excel on me, I can't test it right now. But this should get you started.
Something like this which
Find the true last used cell in any Excel version, and handles a blank result
Parses the string in the last non-blank cell (handling any length of alpha then numeric)to update the next blank cell
Sub GetTrueLastCell()
Dim rng1 As Range
Dim objRegex As Object
Dim strFirst As String
Set rng1 = Columns("A").Find("*", [a1], xlFormulas)
If Not rng1 Is Nothing Then
Set objRegex = CreateObject("vbscript.regexp")
With objRegex
.Pattern = "^(.+?[^\d])(\d+)$"
If .test(rng1.Value) Then
strFirst = .Replace(rng1.Value, "$1")
rng1.Value = strFirst & (Val(Right$(rng1.Value, Len(rng1.Value) - Len(strFirst)) + 1))
End If
End With
Else
MsgBox "Data range is blank"
End If
End Sub
Assumptions:
Next cell in list is empty
Serial N's only have three digits after 'SN' string (i.e., if it reaches 1000, earlier ones don't need padding, like '0100'
-
Dim rAll As Range, rLast As Range, rNext As Range, iNextSN As Integer
Set rAll = Intersect(Sheet1.Cells(1).CurrentRegion, Sheet1.Columns(1)) ' Column 'A' can be contiguous with others
Set rLast = rAll.Cells(rAll.Cells.Count) ' Last cell in current list
Set rNext = rLast.Offset(1) ' Next cell below current list
iNextSN = CInt(Right(rLast.Value, 3)) ' Get value of last serial N
rNext.Value = "SN" & iNextSN + 1 ' Assemble next SN with increment
-