Duplicate Column next to original Column based on a header name - excel

I have searched quite a bit for this but keep finding where people want to copy to another sheet and that's not what I want. I want to just duplicate a column labeled "Student ID" since it isn't always in column D and to reference the Active Sheet since the sheet isn't always named Sheet1. The additional code then adds a 0 to the end of the data in the new duplicated column and labels the new column "Patron". I am fairly new to VBA so struggling with this.
Range("D:D").Copy
Range("E:E").Insert
Range("E1").Value = "PATRON"
Range("IV1") = 10
Range("IV1").Copy
Range("E1:E" & Range("E" & Rows.Count).End(xlUp).Row).PasteSpecial xlPasteValues, xlPasteSpecialOperationMultiply
Range("IV1").Delete xlShiftUp
End Sub

Something like the following could work:
Option Explicit
Public Sub Example()
DuplicateColumn ThisWorkbook.ActiveSheet, "Student ID", "PATRON"
End Sub
Public Sub DuplicateColumn(ByVal ws As Worksheet, ByVal HeaderName As String, ByVal NewColumnName As String)
' find the header name
Dim ColumnFound As Range
Set ColumnFound = ws.Rows(1).Find(What:=HeaderName, _
After:=ws.Cells(1, 1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False)
' check if it was found
If ColumnFound Is Nothing Then
MsgBox "Column '" & HeaderName & "' was not found.", vbCritical
Exit Sub
End If
' copy that column
With ColumnFound.EntireColumn
.Copy
.Offset(ColumnOffset:=1).Insert
End With
' give the new column a new name
ColumnFound.Offset(ColumnOffset:=1).Value = NewColumnName
' add 0 at the end of that column
ws.Cells(ws.Rows.Count, ColumnFound.Column + 1).End(xlUp).Offset(RowOffset:=1).Value = 0
End Sub

This code finds the column labeled "Student ID" and inserts a new column then copies the data to the new column. Since I'm not sure about what the rest of the code does, I'll leave that to you. Also, to a a zero at the endd of a cell 's data, just do something like cells(row, Col+1).value = cells(row, Col+1).value & "0"
Set sht = ActiveSheet 'set variable to active sheet
' Finds the column NUMBER for Student ID
Col = sht.Rows(1).Find(What:="Student ID", LookIn:=xlValues, LookAt:=xlWhole).Column
Columns(Col + 1).Insert 'insert new column
Columns(Col).Copy Columns(Col + 1) 'copy Student ID column data to new column
Cells(1, Col + 1).Value = "PATRON" 'add header to new column

Use Find to locate header and Concatenate to add the zero.
Option Explicit
Sub macro1()
Const COL_NAME = "Student ID"
Dim ws As Worksheet, rng As Range
Dim r As Long, c As Long, LastRow As Long
Set ws = ActiveSheet
Set rng = ws.Cells.Find(COL_NAME, LookIn:=xlValues, lookat:=xlWhole)
If rng Is Nothing Then
MsgBox "Could not locate column '" & COL_NAME & "'", vbCritical
Exit Sub
Else
r = rng.Row
c = rng.Column
LastRow = ws.Cells(Rows.Count, c).End(xlUp).Row
ws.Columns(c + 1).Insert
ws.Cells(r, c + 1) = "PATRON"
Set rng = ws.Cells(r + 1, c + 1).Resize(LastRow - r)
rng.FormulaR1C1 = "=CONCATENATE(RC[-1],0)"
'rng.Value2 = rng.Value2 'uncomment if you want values not fomulae
End If
End Sub

Related

Issue with inserting / arranging columns using VBA

I have an excel worksheeet which has a number of columns, typically from A to AZ. I've written something in VBA which is supposed to arrange and clean this worksheet by calling other subroutines, each which perform an individual task such as formatting, deleting rows, inserting new columns and moving and renaming existing ones.
I'm very new to VBA, so a lot of what I have written is what I've managed to find on here or google. I'm not sure whether the way I have written this is the best way of performing the task.
The problem I have is that the first part one of the subs (arrangeColumns) which is supposed to insert a new column at A somtimes works. The other times it appears to copy the entire worksheet and duplicate it so that my columns now go from A - AZ and are duplicated again from BA - CZ.
From what what little knowledge I have I've managed to find out that when I run this sub on its own it does work, however when this sub is called from my main part it doesnt peform as it should.
Apart from the very first column not being inserted correctly the rest of the code seems to work. Any help or suggestions welcome! thanks
Sub ArrangeColumns()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("test")
'inserts Index column at A. This is the part that seems to fail and duplicates the worksheet
ws.Range("A1").EntireColumn.Insert
ws.Range("A1").Value = "Index"
'identifies last column
Dim lastColumn As Long
lastColumn = ws.Cells.Find("*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).column
'Finds the column Timestamp: Time and moves to B, renames to Date
Dim column As Range
For Each column In ws.Range("A1:" & Split(ws.Cells(1, lastColumn).Address, "$")(1) & "1").Cells
If column.Value = "Timestamp: Time" Then
column.EntireColumn.Cut
ws.Range("B1").Insert shift:=xlToRight
ws.Range("B1").Value = "Date"
Exit For
End If
Next column
'inserts Time column at C
ws.Range("C1").EntireColumn.Insert
ws.Range("C1").Value = "Time"
'inserts blank column at D
ws.Range("D1").EntireColumn.Insert
ws.Range("D1").Value = "Blank"
'finds the column Body and moves to E
For Each column In ws.Range("A1:" & Split(ws.Cells(1, lastColumn).Address, "$")(1) & "1").Cells
If column.Value = "Body" Then
column.EntireColumn.Cut
ws.Range("E1").Insert shift:=xlToRight
Exit For
End If
Next column
'find the From column and moves to F
For Each column In ws.Range("A1:" & Split(ws.Cells(1, lastColumn).Address, "$")(1) & "1").Cells
If column.Value = "From" Then
column.EntireColumn.Cut
ws.Range("F1").Insert shift:=xlToRight
ws.Range("F1").Value = "From User"
Exit For
End If
Next column
'inserts From Attributed column at G
ws.Range("G1").EntireColumn.Insert
ws.Range("G1").Value = "From Attributed"
'find th To column and moves to H, renames to To User
For Each column In ws.Range("A1:" & Split(ws.Cells(1, lastColumn).Address, "$")(1) & "1").Cells
If column.Value = "To" Then
column.EntireColumn.Cut
ws.Range("H1").Insert shift:=xlToRight
ws.Range("H1").Value = "To User"
Exit For
End If
Next column
'inserts To Attributed at I
ws.Range("I1").EntireColumn.Insert
ws.Range("I1").Value = "To Attributed"
'finds Participants column and moves to J
For Each column In ws.Range("A1:" & Split(ws.Cells(1, lastColumn).Address, "$")(1) & "1").Cells
If column.Value = "Participants" Then
column.EntireColumn.Cut
ws.Range("J1").Insert shift:=xlToRight
Exit For
End If
Next column
'Finds Source column and moves to K
For Each column In ws.Range("A1:" & Split(ws.Cells(1, lastColumn).Address, "$")(1) & "1").Cells
If column.Value = "Source" Then
column.EntireColumn.Cut
ws.Range("K1").Insert shift:=xlToRight
Exit For
End If
Next column
End Sub
Sub deleteFirstRow()
'deletes the first row of the worksheet
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("test")
ws.Rows(1).Delete
End Sub
Sub convertToRange()
'loops throught the worksheet to find all tables and converts to range
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("test")
Dim table As ListObject
For Each table In ws.ListObjects
table.Range.Copy
table.Unlist
Next table
End Sub
Sub clearFilter()
'removes all filters on activesheet
On Error Resume Next
ActiveSheet.ShowAllData
End Sub
Sub formatting()
'if this sub is called after cleaning the columns, then the index will be blank. This uses the column titled '#' to find the lastrow
Dim lastRow As Long
Dim lastColumn As Long
Dim col As Range
Set col = Rows(1).Find("#", LookIn:=xlValues, lookat:=xlWhole)
lastRow = Cells(Rows.Count, col.column).End(xlUp).Row
lastColumn = Cells(1, columns.Count).End(xlToLeft).column
Dim rngAll As Range
Set rngAll = Range(Cells(1, 1), Cells(lastRow, lastColumn))
Dim rngTopRow As Range
Set rngTopRow = Range(Cells(1, 1), Cells(1, lastColumn))
Dim rngSecondRowDown As Range
Set rngSecondRowDown = Range(Cells(2, 1), Cells(lastRow, lastColumn))
With rngAll
.Borders.LineStyle = xlContinuous
.Borders.Weight = xlThin
.Borders.ColorIndex = xlAutomatic
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlCenter
.Borders(xlInsideHorizontal).LineStyle = xlContinuous
.Borders(xlInsideHorizontal).Weight = xlThin
.Borders(xlInsideHorizontal).ColorIndex = xlAutomatic
.Borders(xlInsideVertical).LineStyle = xlContinuous
.Borders(xlInsideVertical).Weight = xlThin
.Borders(xlInsideVertical).ColorIndex = xlAutomatic
End With
'sets the colour, font and row size of the first row
With rngTopRow
.Interior.Color = RGB(48, 84, 150)
.Font.Color = vbWhite
.Font.Bold = True
.RowHeight = 40
End With
'sets colour, borders and row size of rows 2 to lastrow
With rngSecondRowDown
.Interior.Color = RGB(255, 255, 255)
.RowHeight = 50
End With
End Sub
Sub splitDateTime()
'if this sub is called after cleaning the columns, then the index will be blank. This uses the column titled '#' to find the lastrow
'Splits the values in column B from 'dd/mm/yyyy hh:mm:ss' by space and moves 'hh:mm:ss' to column c
Dim lastRow As Long
Dim col As Range
Set col = Rows(1).Find("#", LookIn:=xlValues, lookat:=xlWhole)
lastRow = Cells(Rows.Count, col.column).End(xlUp).Row
For i = 2 To lastRow
Cells(i, 3).Value = Mid(Cells(i, 2).Value, 12, 16)
Cells(i, 2).Value = Left(Cells(i, 2).Value, 10)
Next i
End Sub
Sub columnWidth()
columns("a").columnWidth = 15
columns("b").columnWidth = 11
columns("c:d").columnWidth = 15
columns("e").columnWidth = 30
columns("f:i").columnWidth = 22
columns("j").columnWidth = 40
End Sub
Sub applyFilter()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("test")
Dim rngAll As Range
Dim lastRow As Long
Dim lastColumn As Long
Dim col As Range
Set col = Rows(1).Find("#", LookIn:=xlValues, lookat:=xlWhole)
lastRow = Cells(Rows.Count, col.column).End(xlUp).Row
lastColumn = Cells(1, columns.Count).End(xlToLeft).column
Set rngAll = Range(Cells(1, 1), Cells(lastRow, lastColumn))
rngAll.AutoFilter
End Sub
Sub arrangeWorksheet()
Call clearFilter
Call deleteFirstRow
Call convertToRange
Call ArrangeColumns
Call formatting
Call splitDateTime
Call columnWidth
Call applyFilter
End Sub
There is a bunch of repeated logic/steps in your ArrangeColumns which could be pushed out into a separate reusable method.
For example:
Sub arrangeWorksheet()
Call ArrangeColumns
End Sub
Sub ArrangeColumns()
Dim ws As Worksheet, rwHeaders As Range
Set ws = ThisWorkbook.Sheets("test")
Set rwHeaders = ws.Rows(1) 'headers are here
MoveOrAddColumn rwHeaders, "", "Index", "A"
MoveOrAddColumn rwHeaders, "Timestamp: Time", "Date", "B"
MoveOrAddColumn rwHeaders, "", "Time", "C"
MoveOrAddColumn rwHeaders, "", "Blank", "D"
MoveOrAddColumn rwHeaders, "Body", "", "E"
MoveOrAddColumn rwHeaders, "From", "From User", "F"
MoveOrAddColumn rwHeaders, "", "From Attributed", "G"
MoveOrAddColumn rwHeaders, "To", "To User", "H"
MoveOrAddColumn rwHeaders, "", "To Attributed", "I"
MoveOrAddColumn rwHeaders, "Participants", "", "J"
MoveOrAddColumn rwHeaders, "Source", "", "K"
End Sub
'With all headers in range `rwHeaders`...
'Move a column named `existingColName` to `destColLetter` (if existingColName is supplied)
'Otherwise insert a new column at position `destColLetter`
'Moved/inserted column is given header `newColName` (if supplied)
Sub MoveOrAddColumn(rwHeaders As Range, existingColName, newColName, destColLetter)
Dim m, colRng As Range, f As Range, cDest As Range, moving
Set cDest = rwHeaders.Columns(destColLetter) 'destination if moving, or new column
moving = Len(existingColName) > 0
If moving Then 'moving an existing column?
Set f = rwHeaders.Find(what:=existingColName, lookat:=xlWhole)
If f Is Nothing Then
MsgBox "Column header '" & existingColName & "' not found!"
Exit Sub
Else
If f.column <> cDest.column Then 'check if already in the requested postion
cDest.EntireColumn.Insert shift:=xlToRight
Set cDest = cDest.Offset(0, -1) 're-point reference
f.EntireColumn.Copy cDest
f.EntireColumn.Delete
End If
End If
Else
cDest.EntireColumn.Insert shift:=xlToRight
Set cDest = cDest.Offset(0, -1) 're-point reference
End If
If Len(newColName) > 0 Then cDest.Value = newColName
End Sub

How to copy the column A to M from a row in sheet1 to sheet2 if it doesn't already exist

I would like to select some rows by putting an X in the column L, then copy selected row (Only column A to M) to the next free row in sheet2.
Free row mean there is nothing in the column A to M since there is content in the next column already filled.
The copy shouldn't erase the content already existing after column M.
The row can't be added if it's already in the sheet2 and to test this, I have an unique ID for the row in column M.
Some of the column of the row that should be copied are sometimes empty.
Part of what I tried :
Sub GAtoList()
Dim xRg As Range
Dim xCell As Range
Dim A As Long
Dim B As Long
Dim L As Long
A = Worksheets("knxexport").Range("d" & Worksheets("knxexport").Rows.Count)
B = Worksheets("Sheet2").UsedRange.Rows.Count
If B = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("Sheet2").UsedRange) = 0 Then B = 0
End If
Set xRg = Worksheets("knxexport").Range("L1:L" & A)
Application.ScreenUpdating = False
For L = 1 To xRg.Count
If CStr(xRg(L).Value) = "X" Then
xRg(L).EntireRow.Copy Destination:=Worksheets("Sheet2").Range("A" & B + 1)
B = B + 1
Cells(L, B).EntireRow.Interior.ColorIndex = 4
End If
Next
'Erase the X that select the row I want to copy
Worksheets("knxexport").Columns(12).ClearContents
Worksheets("Sheet2").Columns(12).ClearContents
Application.ScreenUpdating = True
End Sub
Column D is never empty so I use it to check the end of the source sheet
knxexport sheet where I take data
sheet2 where I want to copy them
Please, test the next code:
Sub GAtoList()
Dim sh As Worksheet, shDest As Worksheet, lastRL As Long, LastRM As Long
Dim strSearch As String, rngM As Range, arrCopy, cellF As Range, rngL As Range, cellFAddress As String, i As Long, mtch
strSearch = "X"
Set sh = 'Worksheets("knxexport") 'the sheet to copy from
Set shDest = 'Worksheets("Sheet2") 'the sheet to copy to
shDest.Range("M:M").NumberFormat = "#" 'format the M:M column as text
lastRL = sh.Range("L" & sh.rows.count).End(xlUp).row
Set rngL = sh.Range("L2:L" & lastRL) 'the range to search for "X"
Set cellF = rngL.Find(what:=strSearch, After:=sh.Range("L2"), LookIn:=xlValues, Lookat:=xlWhole, MatchCase:=False)
If Not cellF Is Nothing Then 'If at least an "X" string has been found:
cellFAddress = cellF.Address 'memorize its (first) address
Do
LastRM = shDest.Range("M" & shDest.rows.count).End(xlUp).row 'last row in M:M
If LastRM > 1 Then 'if there already are IDs:
Set rngM = shDest.Range("M2:M" & LastRM)
mtch = Application.match(sh.cells(cellF.row, "M").Value, rngM, 0)
If IsError(mtch) Then 'no ID found
shDest.Range("A" & LastRM + 1 & ":" & "M" & LastRM + 1).Value = _
sh.Range(sh.Range("A" & cellF.row), sh.Range("M" & cellF.row)).Value
Else
Debug.Print sh.cells(cellF.row, "M").Value & " already existing..." 'warn in case of ID existence...
End If
Else
'copy in the second row
shDest.Range("A2:M2").Value = _
sh.Range(sh.Range("A" & cellF.row), sh.Range("M" & cellF.row)).Value
End If
Set cellF = rngL.FindNext(cellF)
Loop While cellF.Address <> cellFAddress 'exit to avoid restarting loop from the memorized address
Else
MsgBox strSearch & " could not be found in ""L:"" column...": Exit Sub
End If
End Sub

Excel VBA: How do I add text to a blank cell in a specific column then loop to the next blank cell and add text?

I need a macro to add text to blank cells in Column A. The macro needs to skip cells that have text. The macro needs to stop looping at the end of the data set.
I am trying to use an If Else statement, but I think I'm on the wrong track. My current, non-working code is below. Thank you so much - I'm still new to VBA
Sub ElseIfi()
For i = 2 To 100
If Worksheets("RawPayrollDump").Cells(2, 1).Value = "" Then
Worksheets("RawPayrollDump").Cells(2, 1).Value = "Administration"
Else if(not(worksheets("RawPayrollDump").cells(2,1).value="")) then 'go to next cell
End If
Next
End Sub
To find the last row of data, use the End(xlUp) function.
Try this code. It replaces all empty cells in column A with Administration.
Sub ElseIfi()
Set ws = Worksheets("RawPayrollDump")
lastrow = ws.Cells(Rows.Count, 1).End(xlUp).Row ' last data row
For i = 2 To lastrow ' all rows until last data row
If ws.Cells(i, 1).Value = "" Then ' column A, check if blank
ws.Cells(i, 1).Value = "Administration" ' set text
End If
Next
End Sub
There is no need to loop. Please try this code.
Sub FillBlanks()
Dim Rng As Range
With Worksheets("RawPayrollDump")
Set Rng = Range(.Cells(2, "A"), .Cells(.Rows.Count, "A").End(xlUp))
End With
On Error Resume Next
Set Rng = Rng.SpecialCells(xlCellTypeBlanks)
If Err Then
MsgBox "There are no blank cells" & vbCr & _
"in the specified range.", _
vbInformation, "Range " & Rng.Address(0, 0)
Else
Rng.Value = "Administration"
End If
End Sub
Replace Blanks feat. CurrentRegion
Range.CurrentRegion
Since OP asked for "... stop looping at the end of the data set. ",
I've written this CurrentRegion version.
As I understand it, the end of the data set doesn't mean that there
cannot be blank cells below the last cell containing data in column
A.
Use the 1st Sub to test the 2nd, the main Sub (replaceBlanks).
Adjust the constants including the workbook (in the 1st Sub) to fit your needs.
Criteria is declared as Variant to allow other data types not just strings.
The Code
Option Explicit
Sub testReplaceBlanks()
Const wsName As String = "RawPayrollDump"
Const FirstCellAddress As String = "A2"
Const Criteria As Variant = "Administration"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
replaceBlanks ws, FirstCellAddress, Criteria
End Sub
Sub replaceBlanks(Sheet As Worksheet, _
FirstCellAddress As String, _
Criteria As Variant)
' Define column range.
Dim ColumnRange As Range
Set ColumnRange = Intersect(Sheet.Range(FirstCellAddress).CurrentRegion, _
Sheet.Columns(Sheet.Range(FirstCellAddress) _
.Column))
' To remove the possibly included cells above the first cell:
Set ColumnRange = Sheet.Range(Range(FirstCellAddress), _
ColumnRange.Cells(ColumnRange.Cells.Count))
' Note that you can also use the addresses instead of the cell range
' objects in the previous line...
'Set ColumnRange = sheet.Range(FirstCellAddress, _
ColumnRange.Cells(ColumnRange.Cells.Count) _
.Address)
' or a mixture of them.
' Write values from column range to array.
Dim Data As Variant
If ColumnRange.Cells.Count > 1 Then
Data = ColumnRange.Value
Else
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = ColumnRange.Value
End If
' Modify array.
Dim i As Long, k As Long
For i = 1 To UBound(Data)
If IsEmpty(Data(i, 1)) Then Data(i, 1) = Criteria: k = k + 1
Next i
' Write modified array to column range.
' The following line is used when only the first cell is known...
'Sheet.Range(FirstCellAddress).Resize(UBound(Data)).Value = Data
' ...but since the range is known and is the same size as the array,
' the following will do:
ColumnRange.Value = Data
' Inform user.
If k > 0 Then GoSub Success Else GoSub Fail
Exit Sub
' Subroutines
Success:
MsgBox "Wrote '" & Criteria & "' to " & k & " previously " _
& "empty cell(s) in range '" & ColumnRange.Address & "'.", _
vbInformation, "Success"
Return
Fail:
MsgBox "No empty cells in range '" & ColumnRange.Address & "'.", _
vbExclamation, "Nothing Written"
Return
End Sub

Check if all column values exists in another list

The excel vba macro I have created goes through an entire column and searches each value in the column against another column found on another worksheet. I have a T/F column where I mark down "T" if it is found, "F" if it is not found. However, I feel like the way I am doing it might not be very efficient, as the macro takes about 30 minutes to go through 31,000 rows of values to be searched from another column with about 27,000 number of values.
For a simple illustration, I have included a few images which explains what the macro does.
Initially the T/F column will be empty. Only after executing the macro, would it be filled. I loop through each row in column A and try to find the value against the SearchCol in the next picture.
Here is the vba code I am currently using.
Sub CheckIfValuesExist()
Dim ActiveWS As Worksheet, WS2 As Worksheet
Dim ValueColLetter As String, SearchColLetter As String, TFColLetter As String
Dim LastRow As Long, i As Long
Dim target As Variant, rng As Range
Set ActiveWS = ActiveWorkbook.Worksheets(1)
Set WS2 = ActiveWorkbook.Worksheets(2)
ValueColLetter = "A"
SearchColLetter = "A"
TFColLetter = "B"
LastRow = ActiveWS.Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, _
LookIn:=xlFormulas).Row
For i = 2 To LastRow
target = ActiveWS.Range(ValueColLetter & i).Value
If target <> "" Then
With WS2.Range(SearchColLetter & ":" & SearchColLetter) 'searches all of column A
Set rng = .Find(What:=target, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not rng Is Nothing Then
ActiveWS.Range(TFColLetter & i).Value = "T" 'value found
Else
ActiveWS.Range(TFColLetter & i).Value = "F" 'value not found
End If
End With
End If
Next i
End Sub
The macro works as intended, I just find it to be slow. Is there any better way to do the same thing but in a quicker manner?
Check Column Against Column
Array Match Range Version
Sub CheckIfValuesExist()
Const cSheet1 As Variant = 1 ' Value Worksheet Name/Index
Const cSheet2 As Variant = 2 ' Search Worksheet Name/Index
Const cFirst As Long = 2 ' First Row
Const cVal As Variant = "A" ' Value Column
Const cSrc As Variant = "A" ' Search Column
Const cTF As Variant = "B" ' Target Column
Const cT As String = "T" ' Found String
Const cF As String = "F" ' Not Found String
Dim RngS As Range ' Search Range
Dim vntV As Variant ' Value Array
Dim vntT As Variant ' Target Array
Dim LastV As Long ' Value Last Column Number
Dim LastS As Long ' Search Last Column Number
Dim i As Long ' Value/Target Row Counter
Dim dummy As Long ' Match Dummy Variable
With Application
.Calculation = xlCalculationManual
.ScreenUpdating = False
End With
On Error GoTo ProcedureExit
With ThisWorkbook.Worksheets(cSheet1)
LastV = .Columns(.Cells(1, cVal).Column).Find("*", , -4123, , 2, 2).Row
vntV = .Range(.Cells(cFirst, cVal), .Cells(LastV, cVal))
End With
With ThisWorkbook.Worksheets(cSheet2)
LastS = .Columns(.Cells(1, cSrc).Column).Find("*", , -4123, , 2, 2).Row
Set RngS = .Range(.Cells(cFirst, cSrc), .Cells(LastS, cSrc))
ReDim vntT(1 To UBound(vntV), 1 To 1)
For i = 1 To UBound(vntV)
On Error Resume Next
If vntV(i, 1) <> "" Then
dummy = Application.Match(vntV(i, 1), RngS, 0)
If Err Then
vntT(i, 1) = cF
Else
vntT(i, 1) = cT
End If
End If
On Error GoTo 0
Next
End With
On Error GoTo ProcedureExit
With ThisWorkbook.Worksheets(cSheet1)
.Range(.Cells(cFirst, cTF), .Cells(.Rows.Count, cTF)).ClearContents
.Cells(cFirst, cTF).Resize(UBound(vntT)) = vntT
End With
ProcedureExit:
With Application
.Calculation = xlCalculationAutomatic
.ScreenUpdating = True
End With
End Sub
Let us assume that data included in Sheet 1.
Try:
Option Explicit
Sub VlookUp()
Dim LastRowSV As Long, LastRowV As Long, Counts As Long
Dim wsName As String
Dim wsListSV As Range, cellSV As Range, wsListV As Range, cellV As Range
With ThisWorkbook.Worksheets("Sheet1")
'Find the last row of Search Values
LastRowSV = .Cells(.Rows.Count, "D").End(xlUp).Row
'Find the last row of Values
LastRowV = .Cells(.Rows.Count, "A").End(xlUp).Row
'Set the list with the Search Values
Set wsListSV = .Range(Cells(2, 4), Cells(LastRowSV, 4))
'Set the list with the Values
Set wsListV = .Range(Cells(3, 1), Cells(LastRowV, 1))
'Loop each value in Search Values
For Each cellV In wsListV
Counts = Application.WorksheetFunction.CountIf(wsListSV, cellV)
If Counts <> 0 Then
cellV.Offset(0, 1).Value = "T"
Else
cellV.Offset(0, 1).Value = "F"
End If
Next
End With
End Sub
Result:
Why don't you use the MATCH formula?
If your values are in Col A and the search values are at
the cells $F$5:$F$10 the formula is:
=MATCH(A2,$F$5:$F$10,0)
or if you insist on a T/F result:
=IF(ISERROR(MATCH(A2,$F$5:$F$10,0)),"T","F")
Of cause you can insert this formula also with a macro.

How to create a textjoin worksheet function with dynamic range

I have data where I have many column headers. One of the header is "Text" and one other header is "Value Date". I want to combine the values contained in every row between these columns in another column row-wise.
The problem is the number of columns between these two headers is not constant. It changes with every new ledger I export. So I want my code to be dynamic in such a way that it will identify the column of "Text" and then it will identify the column of "Value Date" and combine everything between in another column row-wise.
This is where I have reached with my code but I don't know why it's not working. I have been trying this for last 3 days only to get nowhere. When I run this code, the result which I get is "TextColumnNo:ValueColumnNo".
Sub TextJoin()
Dim TextColumnNo As Range
Dim ValueColumnNo As Range
Range("A1").Select
ActiveCell.EntireRow.Find("Text").Activate
Set TextColumnNo = Range(ActiveCell.Address(False, False))
Range("A1").Select
ActiveCell.EntireRow.Find("Value").Activate
Set ValueColumnNo = Range(ActiveCell.Address(False, False))
ActiveCell.Offset(1, -1).Select
Application.CutCopyMode = False
ActiveCell.Value = Application.WorksheetFunction.TextJoin(" ", True, _
"TextColumnNo:ValueColumnNo")
ActiveCell.Select
Selection.AutoFill Destination:=ActiveCell.Range("A1:A8524")
ActiveCell.Range("A1:A8524").Select
Selection.Copy
Selection.PasteSpecial Paste:=xlPasteValues
Application.CutCopyMode = False
End Sub
You would need 2 loops for this. One looping through all rows and one looping through the columns to combine the text for each row.
Note that you need to adjust some things like sheet name and output column here.
Option Explicit
Public Sub TextJoin()
Dim ws As Worksheet
Set ws = Worksheets("Sheet1") 'define a worksheet
'find start
Dim FindStart As Range
Set FindStart = ws.Rows(1).Find("Text")
If FindStart Is Nothing Then
MsgBox "start not found"
Exit Sub
End If
'find end
Dim FindEnd As Range
Set FindEnd = ws.Rows(1).Find("Value Date")
If FindEnd Is Nothing Then
MsgBox "start not found"
Exit Sub
End If
'find last used row in column A
Dim lRow As Long
lRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
Dim iRow As Long
For iRow = 2 To lRow 'loop through all rows (2 to last used row)
Dim CombinedText As String
CombinedText = vbNullString 'initialize/reset variable
Dim iCol As Long 'loop through columns for each row (from start to end column)
For iCol = FindStart.Column To FindEnd.Column
CombinedText = CombinedText & ":" & ws.Cells(iRow, iCol).Text 'combine values
Next iCol
ws.Range("Z" & iRow) = CombinedText 'write values in column Z
Next iRow
End Sub
Sub TextJoin()
Dim ColRefText As Long
Dim ColRefValueDate As Long
Const firstcol = "Text"
Const secondcol = "Value Date"
Dim r As Range
Set r = Rows(1).Cells.Find(firstcol)
If Not r Is Nothing Then
ColRefText = r.Column
Set r = Rows(1).Cells.Find(secondcol)
If Not r Is Nothing Then
ColRefValueDate = r.Column
End If
End If
If ColRefValueDate + ColRefText > 0 Then
With Cells(2, Worksheets(1).Columns.Count).End(xlToLeft).Offset(0, 1)
.Formula = Replace("=" & Cells(2, ColRefText).AddressLocal & "&" & Cells(2, ColRefValueDate).AddressLocal, "$", "")
.Copy Range(.Address, Cells(ActiveSheet.UsedRange.Rows.Count, .Column).Address)
End With
End If
End Sub

Resources