Old Prompt
I've been trying to find a method of delimitating cells in Excel using the new line in the text with no luck. I need to delimitate a Cells string into multiple columns separated by the New Lines in the string so now I'm trying to find a way to do this with Visual Basics App. Does anyone have any useful advice or recommendations?
New Prompt
In the earlier portion of this assignment the goal was:
recognize Chr(10)
delimitate the text downward into a new column
keep the data from the same row
Previously I did not know there was a character that represented the new line. This is to say that I've found the solution to my problem and shared my results below.
OP ANSWER
It's me again. I know this might seem a bit messy and maybe not as efficient as it could be, but this is essentially what I was looking for. I hope this helps anyone in the future. Feel free to message me with any questions or concerns.
CODE
Sub Test()
Dim CountRows, FirstPortion, FullString, Row, Col
'Manually Set This Value
Row = 2
Col = 4
CountRows = 8
' '~~maybe i should count number of rows and increase count each time that a row is delimitated
' '~~~or just the same increase count when a new row is inserted
' '~~this would avoid the process of rechecking that a row has more to be delimitated
'------------------------------***{ROW TRAVERSAL}***---------------------------------
Do While Row < CountRows + 1
'---------------------------***{INITIALIZE}***-----------------------------------
FullString = Cells(Row, Col)
Debug.Print "Row"; Row; ":"; "FullString:"
Debug.Print FullString
'--------------------------***{REPLACEMENT}***----------------------------------
'If the row we point to contains a new line char then we want to replace newlines with "."
If InStr(FullString, Chr(10)) > 0 Then
Debug.Print "Row"; Row; " Info:"; " There is more than one line"
' 'replaces new line char with periods
FullString = Trim(Replace(FullString, Chr(10), "."))
Debug.Print "Row"; Row; ":"; "FullString:"
Debug.Print FullString
' 'counts number of periods in the current row
' '****{might not need}****
' Count = Len(Cells(Row, Col)) - Len(Replace(Cells(Row, 4), ".", ""))
End If
'---------------------------***{EXTRACTION}***----------------------------------
'------------------------------***{LOOP}***----------------------------------
'If the Row we point to contains a "." then that implies there is more names to be delimitated
'Knowing this we want to isolate the first portion of the String and isolate the remaining portion
'the remaining portion should be moved to the next inserted row
If InStr(FullString, ".") > 0 Then
Debug.Print "Row"; Row; " Info:"; " There is more than one period"
FirstPortion = Left(FullString, InStr(FullString, ".") - 1)
Debug.Print "Row"; Row; ":"; "FirstPortion:"
Debug.Print FirstPortion
FullString = Right(FullString, (Len(FullString) - Len(FirstPortion) - 1))
Debug.Print "Row"; Row; ":"; "FullString:"
Debug.Print FullString
'-----------------------***{INSERTION}***----------------------------------
'Now that the strings are seperated we must insert a new row to move the information to
Rows(Row + 1).Insert
CountRows = CountRows + 1
Debug.Print "Update the Row Count:"; CountRows
'-----------------------***{COPY DATA}***-----------------------------------
'Copy the relative data into the new row
Rows(Row).Copy Rows(Row + 1)
'-------------------***{DELIMITATE NAMES}***--------------------------------
'Set Current Row to first name to be delimitated
Cells(Row, Col) = FirstPortion
'Set Next Row to remaining names
Cells(Row + 1, Col) = FullString
End If
Row = Row + 1
Debug.Print "Row Pointing to:"; Row
Loop
Exit Sub
End Sub
DUMMY DATA
RESULT
Related
Data Sheet
I have two workbooks with the same content. I am copying and pasting the amount values from one workbook sheet to another when the project number and division is the same. The amount has to be pasted in the row where there is a match. The issue I am facing is all the amounts are getting copied but not pasted near the respective match.
The code I have used is as follows:
ws1PRNum = "E" 'Project Number
ws1Div = "I" 'Division
ws2PRNum = "E" 'Project Number
ws2Div = "I" 'Division
'Setting first and last row for the columns in both sheets
ws1PRRow = 5 'The row we want to start processing first
ws1EndRow = wsSrc.UsedRange.Rows(wsSrc.UsedRange.Rows.count).Row
ws2PRRow = 5 'The row we want to start search first
ws2EndRow = wsDest.UsedRange.Rows(wsDest.UsedRange.Rows.count).Row
For i = ws1PRRow To ws1EndRow 'first and last row
searchKey = wsSrc.Range(ws1PRNum & i) & wsSrc.Range(ws1Div & i) 'PR line and number is Master Backlog
'if we have a non blank search term then iterate through possible matches
If (searchKey <> "") Then
For j = ws2PRRow To ws2EndRow 'first and last row
foundKey = wsDest.Range(ws2PRNum & j) & wsDest.Range(ws2Div & j) 'PR line and number in PR Report
'Copy result if there is a match between PR number and line in both sheets
If (searchKey = foundKey) Then
'Copying data where the rows match
wsDest.Range("AJ5", "AU1200").Value = wsSrc.Range("AJ5", "AU1200").Value
wsDest.Range("BB5", "BM1200").Value = wsSrc.Range("BB5", "BM1200").Value
wsDest.Range("BT5", "BU1200").Value = wsSrc.Range("BT5", "BU1200").Value
Exit For
End If
Next
End If
Next
This is the area that is causing an issue. As seen in the picture the amounts are pasted even in rows where the division and project number are empty. Any answer for the same would be highly appreciated as I am not well versed with VBA.
You can do this:
wsDest.Range("AJ" & j, "AU" & j).Value = wsSrc.Range("AJ" & i, "AU" & i).Value
'etc...
or with a bit less concatenation:
wsDest.Rows(j).Range("AJ1:AU1").Value = wsSrc.Rows(i).Range("AJ1:AU1").Value
I have two columns that need to have their contents combine. I want the combining to occur on every row of form.
With Cells(PoleRow, 25) = Cells(PoleRow, 25).Value & " / " & Cells(PoleRow, 123).Value
End With
With this code, it does not error out but it also does not do anything. I want to combine everything in column 123 into column 25.
Try to make the code as simple as possible. E.g., write the left concatenated part to a string and pass the string to a value. Then it looks maintainable and eas to understand:
Sub TestMe()
Dim poleRow As Long
poleRow = 1
With Worksheets(1)
Dim union As String
union = .Cells(poleRow, 25) & " / " & .Cells(poleRow, 123)
.Cells(poleRow, 25) = union
End With
End Sub
You just can't do it in one lane :)
Earlier you should declare starting row and last row for which you want to iterate.
For PoleRow=1 to 125 ' decalring start row = 1 and last row, you can also declare last row by VBA code
With Cells(PoleRow, 25)
Cells(PoleRow,25) = Cells(PoleRow, 25).Value2 & " / " & Cells(PoleRow, 123).Value2
End With
Next PoleRow
How to declare last row/coll: https://www.thespreadsheetguru.com/blog/2014/7/7/5-different-ways-to-find-the-last-row-or-last-column-using-vba
I am relatively new to Macros and VBA in Excel, so I need some guidance on how to solve my current issue.
The end goal of my project is to have a macro compare two sets of data organized into rows and columns (We'll say table A is the source data, and table B is based off of user input). Each row in table B should correspond to a row in table A, but they could be out of order, or there could be incorrect entries in table B.
My thought is that for the first row in each table, the macro would compare each cell left to right:
If Sheets("sheet1").Cells(2, 1) = Sheets("sheet2").Cells(2, 1) Then
If Sheets("sheet1").Cells(2, 2) = Seets("sheet2").Cells(2, 2)
Ect, ect.
My problem comes in when the Cell in table B does not match Table A.
First, I would want it to check B row 1 against the next row in A, and keep going throughout table A until it finds a "complete match" with all five columns of the row matching.
I've been trying to do this with Else if and For/Next staements
For row= 2 to 10
'if statements go here
Else If Sheets("sheet1").Cells(2, 1) <> Sheets("sheet2").Cells(2, 1)
Next row
I may be completely misunderstanding the syntax here, but I have yet to produce a situation where if the criteria is not met, it goes to the next row.
If no complete match is found, the last cell in table B row 1 that couldn't be matched should be highlighted.
Then regardless of whether a match was found or not, we would move to table B row 2, and start the whole process over.
So, I have the logic worked out (I think), where the comparison ifs would be inside a loop (or something) that would cycle through table A row by row. Then that whole process would be in another loop (or something) that would cycle through Table B.
At the end of the process, there would either be no highlighted cells showing that all entered data is correct, or cells would be highlighted showing data that do no match.
I am fairly certain that the cycling through table B is not the issue. Rather, I'm having difficulty getting the Macro to move to the next table A row if something doesn't match.
Please let me know if I need to elaborate on anything.
Thanks!
You could try:
Option Explicit
Sub test()
Dim Lastrow1 As Long, Lastrow2 As Long, i As Long, j As Long
Dim Str1 As String, Str2 As String
'Find the last row of sheet 1
Lastrow1 = Sheet1.Cells(Sheet1.Rows.Count, "A").End(xlUp).Row
'Find the last row of sheet 2
Lastrow2 = Sheet2.Cells(Sheet2.Rows.Count, "A").End(xlUp).Row
For i = 2 To Lastrow1
'Let us assume that table has 3 columns. Merge 3 columns' values and create a string for each line
Str1 = Sheet1.Cells(i, 1).Value & "_" & Sheet1.Cells(i, 2).Value & "_" & Sheet1.Cells(i, 3).Value
For j = 2 To Lastrow2
'Let us assume that table has 3 columns. Merge 3 columns' values and create a string for each line
Str2 = Sheet2.Cells(j, 1).Value & "_" & Sheet2.Cells(j, 2).Value & "_" & Sheet2.Cells(j, 3).Value
'If both strings match a message box will appear
If Str1 = Str2 Then
MsgBox "Line " & i & " in table A match with line " & j & " in table B!"
Exit For
End If
Next j
Next i
End Sub
Sheet 1 structure:
Sheet 2 structure:
In the following program, what I am trying to do is scan the "yes" column of a specific range of sheets in a workbook that a user fills out, and wherever the user puts an "x" within that specific "Yes" column range, it will identify the associated item of the question marked in that row and copy the item code associated with that question (e.g. C3) into a Summary page for logging purposes.
The problem is that the code does not copy the item onto the summary page as intended when the for loop iterates through the desired range of sheets. However, if I comment out the for loop code and write Sheets(6).Select instead of Sheets(i).Select, for example, it will copy the "x" marked items onto the summary page for sheet index #6 as intended. This leads me to believe my copy+paste part of the code works (between the while loop statements), but the for loop fails somehow.
Can somebody please help me identify the source of the error? I understand that this code is not efficient, such as the excessive use of .select and non-dynamic declarations, but if I wanted to keep as much of the code the same as possible, how could I modify it to make it loop through all the sheets as I intended?
Thanks
Sub DSR_Autofill()
' Variable Declarations:
Dim x_count As Long 'keeps track of how many "x"s you have
Dim i As Long 'for loop index
Dim n As Long 'while loop index
Dim item_a As String 'Letter part of Item
Dim item_b As String 'Number part of Item
' Variable Initializations:
x_count = 0 'start x count at zero
' Clear Previous Data:
Sheets(2).Range("A25:A29").ClearContents 'Clear Summary Pages before scanning through
Sheets(3).Range("A18:A200").ClearContents
' Main Data Transfer Code:
For i = 5 To i = 20 'Starts at "Process Control" and ends on "Product Stewardship"
Sheets(i).Select 'Select current indexed worksheet and...
Range("D15").Select '...the first item cell in the "Yes" Column
n = 0 'initialize n to start at top item row every time
Do While ActiveCell.Offset(n, -3) <> Empty 'Scan down "YES" column until Item Column (just "A" Column)...
'...has no characters in it (this includes space (" "))
If (ActiveCell.Offset(n, 0) = "x" _
Or ActiveCell.Offset(n, 0) = "X") Then 'If an "x" or "X" is marked in the "YES" column at descending...
'...cells down the column, at an offset specified by the for loop index n
item_a = ActiveCell.Offset(n, -3).Value ' Store Letter value
item_a = Replace(item_a, "(", "") ' Get rid of "(", ")", and " " (space)
item_a = Replace(item_a, ")", "") ' characters that are grabbed
item_a = Replace(item_a, " ", "")
item_b = ActiveCell.Offset(n, -2).Value ' Store number value
item_b = Replace(item_b, "(", "") ' Get rid of "(", ")", and " " (space)
item_b = Replace(item_b, ")", "") ' characters that are grabbed
item_b = Replace(item_b, " ", "")
x_count = x_count + 1 ' increment the total x count
If (x_count > 5) Then ' If there are more than 5 "x" marks...
Sheets("SUMMARY P.2").Activate ' ...then continue to log in SUMMARY P.2 and...
Range("A18").Select ' ...choose "Item" column, first cell
ActiveCell.Offset((x_count - 6), 0).Value = (item_a & item_b)
'Insert concatenated value of item_a and item_b (for example "A" & "1" = "A1")
'at the cells under the "Item" column, indexed by x_count
Else ' If there are less than 5 "x" marks...
Sheets("SUMMARY P.1").Activate ' ...log in SUMMARY P.1 and...
Range("A25").Select ' ...choose "Item" column, first cell
ActiveCell.Offset((x_count - 1), 0).Value = (item_a & item_b)
End If
End If
n = n + 1
Sheets(i).Select 'Return back to current sheet before running again
Range("D15").Select
Loop 'syntax for continuation of while loop
Next i 'syntax for continuation of for loop
If (x_count > 5) Then 'Bring user back to the Summary Page where the last Item was logged
Sheets("SUMMARY P.2").Select
Else
Sheets("SUMMARY P.1").Select
End If
End Sub
Take out the second "i = " in your For line:
For i = 5 To 20
I have excel cells which contain entries like this:
name/A/date
name/B/date
name/C/date
Cell content is displayed on multiple lines in the same cell. I would like to make only "name" bold for all entries. I recorded a macro and I think the solution must be something like this:
ActiveCell.FormulaR1C1 = "name/A/date" & Chr(10) & "name/B/date" & Chr(10) & "name/C/date"
With ActiveCell.Characters(Start:=25, Length:=4).Font
.FontStyle = "Bold"
End With
What I don't know is how to get the start value and the length of each entry. Anyone got an idea?
Have it now:
lngPos = InStr(ActiveCell.Value, "/")
With ActiveCell.Characters(Start:=1, Length:=lngPos - 1).Font
.FontStyle = "Bold"
End With
Inspired by various research in the last few days:
Dim totalVals, startPos(), endPos(), i, j, strLen As Long
Dim currLine As String
' Split the cell value (a string) in lines of text
splitVals = Split(ActiveCell.Value, Chr(10))
' This is how many lines you have
totalVals = UBound(splitVals)
' For each line, you'll have a character where you want the string to start being BOLD
ReDim startPos(0 To totalVals)
' And one character where you'll want it to stop
ReDim endPos(0 To totalVals)
' The value of the current line (before we loop on ActiveCell.Value) is empty
currLine = ""
For i = 0 To totalVals ' For each line...
' Length of the string currently treated by our code : 0 if no treatment yet...
strLen = Len(currLine)
' Here we parse and rewrite the current ActiveCell.Value, line by line, in a string
currLine = currLine & IIf(currLine = "", "", Chr(10)) & splitVals(i)
' At each step (= each line), we define the start position of the bold part
' Here, it is the 1st character of the new line, i.e. strLen + 1
startPos(i) = strLen + 1
' At each step (= each line), we define the end position of the bold part
' Here, it is just before the 1st "/" in the current line (hence we start from strLen)
endPos(i) = InStr(IIf(strLen = 0, 1, strLen), currLine, "/")
Next i
' Then we use the calculated positions to get the characters in bold
For j = 0 To UBound(startPos)
ActiveCell.Characters(startPos(j), endPos(j) - startPos(j)).Font.FontStyle = "Bold"
Next j
It might be a bit overdone, butI have tested it and it works like a charm. Hope this helps!
The answers above are perfectly fine. Since its related I wanted to include a similar routine I wrote to solve a formatting thing in my wife's macros.
in her situation we were consolidating string and wrote the concatenation into a single cell separated by a vbCrLf (Chr(10)) in her final output it would look something like this
Category number 1:
Category # 2:
Category 3:
The length of each category was different, and the # of categories may vary from 1 cell to the next. The pasted subroutine worked great
Sub BoldCategory()
RowCount = ActiveSheet.UsedRange.Rows.Count
Set MyRange = ActiveSheet.Range(Cells(2, 1), Cells(RowCount, 1))
For Each Cell In MyRange
i = 1
LineBreak = 1
Do While LineBreak <> 0
EndBoldPoint = InStr(i, Cell.Value, ":") + 1
BoldLength = EndBoldPoint - i
Cell.Characters(Start:=i, Length:=BoldLength).Font.FontStyle = "Bold"
LineBreak = InStr(i, Cell.Value, Chr(10))
i = LineBreak + 1
Loop
Next Cell
End Sub
So the ":" was the character I was keying in on to get the end point. the Chr(10) told me when 1 line ended and the next line began. When the last line was reached instr returned 0 therefore the while loop exits.