Extract 1st letter from cell concatenate with another cell paste in third cell, then next row - excel

I need to extract 1st letter from cell B2 concatenate with cell C2 paste in cell A2,
then move to next row and repeat till last data row.
I have the following, which partially works, but only works for the first row A2 then fills down this one string through all the rows till last data row.
Sub UserName()
Dim rng As range
Dim lastRow As Long
With Sheets("sheet1")
lastRow = .range("E" & .Rows.Count).End(xlUp).Row
End With
For Each rng In Sheets("Sheet1").range("A2:A" & lastRow)
rng.Value = fUserName(rng.Value)
Next
End Sub
The function
Function fUserName(ByVal strUserName As String) As String
Dim r As String
r = range("B2").Select
strUserName = Left(Trim(r), 1) & " " & range("C2")
fUserName = strUserName
End Function

IMHO you don't need VBA for that. Just use formula in A2
=CONCATENATE(LEFT(B2, 1),C2)
And then just replicate it for all cells that contain data.

Try below code. I have combined both your procedure.
No need of using a function , No need of For each loop
Sub UserName()
Dim lastRow As Long
With Sheets("sheet1")
lastRow = .Range("C" & .Rows.Count).End(xlUp).Row
End With
Range("A1:A" & lastRow).FormulaR1C1 = "= left(RC[1],1) & RC[2]"
End Sub

Your function is wrong, you are passing strUserName to the function but then setting the same variable within the function, however the real source of your issue is that you are using static references in your function so it does not matter which cell your sub routine is dealing with the function looks a cells B2 and C2.
I would get rid of the function all together and just replace the line
rng.Value = fUserName(rng.Value)
With
rng.Value = Left(Trim(rng.offset(0,1)), 1) & " " & rng.offset(0,2)
If you really want to use a function you need to pass the range to the function, not the value of the active cell as this has no bearing on the values of the other cells around it.

You need to pass the range into the function:
Sub UserName()
Dim rng As range
Dim lastRow As Long
With Sheets("sheet1")
lastRow = .range("E" & .Rows.Count).End(xlUp).Row
End With
For Each rng In Sheets("Sheet1").range("A2:A" & lastRow)
rng.Value = fUserName(rng)
Next
End Sub
Function fUserName(rn as Range) As String
fUserName = Left(Trim(rn(1,2).value), 1) & " " & rn(1,3).value
End Function

Well obviously B2 and C2 are hardcoded values so they do not change. You need to make those change by using a range object, for instance. Here's a pseudo-code of what I would do. I leave it up to you to make the necessary adjustments to make it work (because I don't see much effort in your question).
Function fUserName(rng as Range) as String
fUserName = Left(Trim(rng.Offset(0, 1).value), 1) & " " & rng.Offset(0, 2).value
End Function
Instead of calling fUserName() with rng.value, just put in rng. This will use the range object to get the proper rows for B and C.

Following code select first blank row
Sub SelFrstBlankRow()
Dim r1 As Range, r2 As Range, r3 As Range
Set r1 = Sheets("Sheet1").Range("a20")
Set r2 = Sheets("Sheet1").Range("u20")
Set r3 = Range(r1.End(xlUp), r2.End(xlUp)) 'r3 is the 1st blank row
r3.Select
End Sub

Related

Formula in first blank and filled down to end of data

I have the below code where in all other columns there is many populated rows, what I need this formula to do in column F is to find the first blank, then place the formula in it and fill it down to the last row.
What is currently happening is I have the range as F26 as this is usually first blank but this could change and I want the code to identify this and also have the formula dynamically know what row it is on, so for example if one month the first blank was in cell F30 the range would find it and the formula would start as E30*G30.
Any help would be greatly appreciated.
Private Sub calc()
Dim lastrow As Long
Dim rng As Range
lastrow = ThisWorkbook.Worksheets("Indiv").Cells(Rows.Count, 1).End(xlUp).Row
Set rng = Range("F26:F" & lastrow)
rng.Formula = "=Round((E26*G26),2)"
End Sub
You need to find the first free row in column F and then bulid your formula with this row:
Option Explicit
Private Sub calc()
Dim ws As Worksheet ' define worksheet
Set ws = ThisWorkbook.Worksheets("Indiv")
Dim LastRowA As Long ' find last used row in column A
LastRowA = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim FirstFreeRowF As Long ' find first free row in column F (if first 2 rows have data)
FirstFreeRowF = ws.Cells(1, "F").End(xlDown).Row + 1
' fix issue if first or second row is empty
If FirstFreeRowF = ws.Rows.Count + 1 Then
If ws.Cells(1, "F").Value = vbNullString Then
FirstFreeRowF = 1
ElseIf ws.Cells(2, "F").Value = vbNullString Then
FirstFreeRowF = 2
End If
End If
' define range to add formula
Dim Rng As Range
Set Rng = ws.Range("F" & FirstFreeRowF, "F" & LastRowA)
' add formula
Rng.Formula = "=Round((E" & FirstFreeRowF & "*G" & FirstFreeRowF & "),2)"
End Sub
So this will consider F5 the first free row and fill in the formula in the selected range as seen below:
I think you should find the last used row in column F, so that you could know the next row is blank
lastrowF=sheets(sheetname).range("F" & rows.count).end(xlup).row
So the next row would be like
range("F" & lastrowF+1).formula="Round((E" & lastrowF+1 & "*G" & lastrowF+1 & ",2)"

VBA macro: If Range Contains Words from Another Range Then Type x in Third Range

I would like to solve the following problem:
In Worksheet1 I have a range in text form from O3 to O4500. If the cells in this range contain certain words, I want an "x" to be put in the range U3:U4500 (in the same row). The words to be tested are in range B4:B15 in another Worksheet (Worksheet2).
I made it work with the following code (solution1), but now I don't want to type the code manually for word1, word2, words3... instead it should be taken from the other range in Worksheet 2 (see my draft below in solution2). I believe the problem are the "* *" which are missing when I use the referral to the other range.
Any help is very much appreciated!
Sub solution1()
Dim i As Long
For i = 3 To 4500
If LCase$(Worksheet1.Range("O" & i).Value) Like "*word1*" Or _
LCase$(Worksheet1.Range("O" & i).Value) Like "*word2*" Or _
LCase$(Worksheet1.Range("O" & i).Value) Like "*word3*" Then
Worksheet1.Range("U" & i).Value = "x"
End If
Next
End Sub
Sub solution2()
Dim i As Long, c As Long
For i = 3 To 4500
For c = 4 To 15
If LCase$(Worksheet1.Range("O" & i).Value) Like LCase$(Worksheet2.Range("B" & c).Value) Then
Worksheet1.Range("U" & i).Value = "x"
End If
Next
Next
End Sub
try something like:
Sub solution2()
Dim i As Long, c As Long
searchstring = LCase$(Worksheets("Worksheet2").Range("B1").Value & "|" & Worksheets("Worksheet2").Range("B2").Value & "|" & Worksheets("Worksheet2").Range("B3").Value)
For i = 2 To 9
If Len(LCase$(Worksheets("Worksheet1").Range("O" & i).Value)) < 1 Then GoTo neexxtt
'line above prevents empty lines to be marked
If InStr(searchstring, LCase$(Worksheets("Worksheet1").Range("O" & i).Value)) <> 0 Then Worksheets("Worksheet1").Range("U" & i).Value = "x"
neexxtt:
Next
End Sub
A VBA Lookup: Using an (Array)Formula For Partial Matches
In Excel, in cell U3, you could use the following array formula:
=IF(COUNT(MATCH("*"&Sheet2!$B$4:$B$15&"*",O3,0))>0,"X","")
and copy it down (adjust the lookup worksheet name (Sheet2)).
The following solution is based on this formula avoiding any loops.
Sub VBALookup()
Const Flag As String = "x"
' Reference the ranges.
Dim srg As Range ' Source
Dim drg As Range ' Destination
Dim lrg As Range ' Lookup
With Worksheet1
Set srg = .Range("O3", .Cells(.Rows.Count, "O").End(xlUp))
Set drg = srg.EntireRow.Columns("U")
End With
With Worksheet2
Set lrg = .Range("B4", .Cells(.Rows.Count, "B").End(xlUp))
End With
' Build the array formula.
Dim ArrayFormula As String
ArrayFormula = "=IF(COUNT(MATCH(""*""&'" & Worksheet2.Name & "'!" _
& lrg.Address & "&""*""," & srg.Cells(1).Address(0, 0) & ",0))>0,""" _
& Flag & ""","""")"
' Write the formulae (values).
With drg
' Write the array formula to the first cell.
.Cells(1).FormulaArray = ArrayFormula
' Autofill to the bottom.
.Cells(1).AutoFill .Cells, xlFillDefault
' Not sure, but instead of the previous 2 lines, in Office 365,
' the following single line should work:
'.Cells.Formula = ArrayFormula
' Convert to values (out-comment if you want to keep the formulae).
.Value = .Value
End With
End Sub

Exce VBA how to generate a row count in that starts with specific row and stops at last row? Formula is flawed

So I have what might be a simple issue. I have a worksheet where I'm just hoping to generate a row count starting with cell A4. So A4 = 1, A5 = 2 , etc. The problem is I'm not sure how to configure this with the following goal:
1 - I'm hoping the count starts with cell A4 and ends the count at the final row with data.
The code I have below only works if I manually put A4 = 1, and also populates formulas past the last row unfortunately.
Please help if this is possible.
Sub V14()
With ThisWorkbook.Worksheets("DCT")
.Cells(5, 1).Resize(.Cells(.Rows.Count, 2).End(xlUp).Row - 1).Formula = "=IF(DCT!B5="""","""",DCT!A4+1)"
End With
End Sub
Write Formula to Column Range
The Code
Sub V14()
Const wsName As String = "DCT" ' Worksheet Name
Const tgtRow As Long = 4 ' Target First Row Number
Const tgtCol As String = "A" ' Target Column String
Const critCol As String = "B" ' Criteria Column String
' Define worksheet ('ws').
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets(wsName)
' Define Last Non-Empty Cell ('cel') in Criteria Column ('critCol').
Dim cel As Range
Set cel = ws.Cells(ws.Rows.Count, critCol).End(xlUp)
' Define Target Column Range ('rng').
Dim rng As Range
Set rng = ws.Cells(tgtRow, tgtCol).Resize(cel.Row - tgtRow + 1)
' Define Target Formula ('tgtFormula').
Dim tgtFormula As String
tgtFormula = "=IF('" & wsName & "'!" & critCol & tgtRow _
& "="""","""",MAX('" & wsName & "'!" & tgtCol _
& "$" & tgtRow - 1 & ":" & tgtCol & tgtRow - 1 & ")+1)"
' Write Target Formula to Target Range.
rng.Formula = tgtFormula
' If you just want to keep the values:
'rng.Value = rng.Value
End Sub
I think you might just need an extra IF:
Sub V14()
With ThisWorkbook.Worksheets("DCT")
.Cells(4, 1).Resize(.Cells(.Rows.Count, 2).End(xlUp).Row - 1).Formula = "=IF(DCT!B4="""","""",IF(A3="""",1,SUM(DCT!A3,1)))"
End With
End Sub
Report any question you have or bug you have encountered. If, according to your judgment, this answer (or any other) is the best solution to your problem you have the privilege to accept it (link).
Dim target As String
Dim lastrow As Long
target = "A4"
lastrow = ActiveSheet.UsedRange.Rows.count
'for example
Range(target) = "1"
Range(target).Offset(1, 0) = "2"
Range(Range(target),Range(target).Offset(1, 0)).Select
Selection.AutoFill Destination:=Range(target & ":A" & lastrow + Range(target).Row - 1), Type:=xlFillDefault
You only got to change the target cell, this does the rest.

want to convert Excel formula into VBA code

I wanted to convert below formula to VBA code.
=C1&"`"&K1&"`"&L1&"`"&J1
=VLOOKUP(M1,Data!$A:$J,9,)
=SUMPRODUCT(SUMIF(B1:B,B1,G1:G))
Currently i have enter this formula in 1st row and than copying this formula till the last row used which is taking lot time to apply formula because it has more than million row.
LR1 = Sheets("CRIMS").UsedRange.Rows.Count
Sheets("CRIMS").Range("M1:P1").AutoFill Destination:=Sheets("CRIMS").Range("M1:P" & LR1)
is there any way to convert this formula into VBA code?
For first formula the easiest way would be:
Range("M" & i).FormulaR1C1 = "=RC[-10]&""`""&K&""`""&L&""`""&J"
But for vlookup I prefer dictionaries/collections! It is much much faster.
If You have source data in Data sheet and You want to put that to CRIMS sheet to column M:
Sub vlookup()
Dim names As Range, values As Range
Dim lookupNames As Range, lookupValues As Range
Dim vlookupCol As Object
Dim lastRow As Long
Dim lastRow2 As Long
Dim objekt as Object
With Sheets("Data")
lastRow = Sheets("Data").Cells(Rows.Count, 1).End(xlUp).row
Set names = Sheets("Data").Range("A1:A" & lastRow)
Set values = Sheets("Data").Range("I1:A" & lastRow)
End With
Set objekt = BuildLookupCollection(names, values)
With Sheets("CRIMS")
lastRow2 = 1000000
Set lookupNames = .Range("M1:M" & lastRow)
Set lookupValues = .Range("N1:N" & lastRow)
End With
VLookupValues lookupNames, lookupValues, objekt
Set objekt = Nothing
End Sub
Function BuildLookupCollection(categories As Range, values As Range)
Dim vlookupCol As Object, i As Long
Set vlookupCol = CreateObject("Scripting.Dictionary")
On Error Resume Next
For i = 1 To categories.Rows.Count
Call vlookupCol.Add(CStr(categories(i)), values(i))
Next i
On Error GoTo 0
Set BuildLookupCollection = vlookupCol
End Function
Sub VLookupValues(lookupCategory As Range, lookupValues As Range, vlookupCol As Object)
Dim i As Long, resArr() As Variant
ReDim resArr(lookupCategory.Rows.Count, 1)
For i = 1 To lookupCategory.Rows.Count
resArr(i - 1, 0) = vlookupCol.Item(CStr(lookupCategory(i)))
Next i
lookupValues = resArr
End Sub
Quotation Marks need to be doubled in VBA
Try this:
For i = 1 To LR1
Range("M" & i).Formula = "=C" & i & "&""`""&K" & i & "&""`""&L" & i & "&""`""&J" & i
Range("N" & i).Formula = "=VLOOKUP(M" & i & ",Data!$A:$J,9,)"
Next i
(replace column letters with actual target column)
As mentioned in the comments Looping in this case is highly inefficient.
Use this Code to insert the formulas all at once. It still takes some time for 1 Milion rows though.
Range("M1:M" & LR1).Formula = "=C:C & ""`"" & K:K & ""`"" & L:L & ""`"" & J:J"
Range("N1:N" & LR1).Formula = "=VLOOKUP(M:M,Data!$A:$J,9,)"

Method range of object _global failed

I simply want to use the value in C2 to populate the rest of column C with the same value all the way to the bottom of the data in the sheet.
Sub Testfill1()
'
' Testfill1 Macro
'
'
Sheets(1).Select
lngEndRow = lastCellBlock
Range("C2:C" & lngEndRow).FormulaR1C1 = "1"
End Sub
I simply want to use the value in C2 to populate the rest of column C with the same value all the way to the bottom of the data in the sheet.
This should do what you want:
Sub FillDown()
Range("C2", "C" & rows.Count).FillDown
End Sub
If that doesnt work or doesnt answer your question let me know
This will find the last row in column C with a value and copy whatever is in C2 down to that cell.
Sub CopyDown()
Dim ws As Worksheet
Dim lastRow As Long
Set ws = ThisWorkbook.Sheets("Sheet1")
lastRow = ws.Range("C" & ws.Rows.Count).End(xlUp).Row
ws.Range("C2").Copy ws.Range("C2:C" & lastRow)
End Sub
Try below code
Sub Testfill1()
Dim lastRow As Long
With Sheets("sheet1")
lastRow = .Range("C" & .Rows.Count).End(xlUp).Row
.Range("C2:C" & lastRow).FormulaR1C1 = "1"
End With
End Sub
I simply want to use the value in C2 to populate the rest of column C with the same value all the way to the bottom of the data in the sheet.
I am interpreting "bottom of the data" to mean the extents of your data and not the absolute bottom of the worksheet (the latter being C1048576 in Excel 2007/2010/2013). It isn't clear on whether C2 contains a formula or not so that should likely be left alone and its value stuffed into the remaining cells from C3 down to the extents of the data.
Range("C3:C" & cells(rows.count, 3).end(xlUp).row) = Range("C2").value

Resources