I have an issue with filling blank cells of a column.
I have 4 Column headings in A, B, C, D.
I am trying to create macro to fill blank cells for dynamic data as per attached Data able wherein cell value in Column D is randomly filled and blanked.. Blank cell value needs to filled based on value mentioned in Column A..
I have created the macro but it's working to fill the blank with above value only and not getting the exact result..
Can someone please help...
Below result is expected from coding...
Below is the macro which I have created
Sub FillblankCells()
lr = Cells.Find("*", Cells(1, 1), xlFormulas, xlPart, xlByRows, xlPrevious, False).Row
With Range("D2:D" & lr)
.SpecialCells(xlBlanks).FormulaR1C1 = "=R[-1]C"
.Value = .Value
End With
End Sub
A dictionary is probably overkill, but this should work.
Sub x()
Dim lr As Long, r As Range
Dim oDic As Object
lr = Cells.Find("*", Cells(1, 1), xlFormulas, xlPart, xlByRows, xlPrevious, False).Row
Set oDic = CreateObject("Scripting.Dictionary")
'store column A for each entry in D
For Each r In Range("D2:D" & lr).SpecialCells(xlCellTypeConstants)
oDic(r.Offset(, -3).Value) = r.Value
Next r
'retrieve each column A for blanks in D
For Each r In Range("D2:D" & lr).SpecialCells(xlCellTypeBlanks)
r.Value = oDic(r.Offset(, -3).Value)
Next r
End Sub
This appears to work, it's based on the values in column C.
Sub FillblankCells()
lr = Cells.Find("*", Cells(1, 1), xlFormulas, xlPart, xlByRows, xlPrevious, False).Row
With Range("D2:D" & lr)
.SpecialCells(xlBlanks).FormulaR1C1 = "=IF(R[-1]C[-1]<RC[-1], R[-1]C,R[1]C)"
.Value = .Value
End With
End Sub
You can sort the list before using your formula. Something like this might work:
Sub FillblankCells()
'Declarations.
Dim RngList As Range
Dim DblColumnQuote As Double
Dim DblColumnBuyerName As Double
'Setting.
Set RngList = Range("A1:D1")
DblColumnQuote = 1
DblColumnBuyerName = 4
'Resetting RngList.
Set RngList = Range(RngList, RngList.End(xlDown))
'Sorting RngList.
With RngList.Parent.Sort
.SortFields.Clear
.SortFields.Add Key:=RngList.Columns(DblColumnQuote), _
SortOn:=xlSortOnValues, _
Order:=xlDescending, _
DataOption:=xlSortNormal
.SortFields.Add Key:=RngList.Columns(DblColumnBuyerName), _
SortOn:=xlSortOnValues, _
Order:=xlAscending, _
DataOption:=xlSortNormal
.SetRange RngList
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
.SortFields.Clear
End With
'Filling the blank cells of the Buyer Name column in RngList.
With RngList.Columns(DblColumnBuyerName)
.SpecialCells(xlBlanks).FormulaR1C1 = "=R[-1]C"
.Value = .Value
End With
End Sub
Related
I am stuck with a rather complex search and replace function, which is made up of one large table with 3 columns defining the 1) sheet where to SnR, 2) search term, 3) replacement word. I am testing on a Test sheet with 10 entries, but cant get the script to process any of the cells in range...
Sub FART_find_and_replace_text()
Dim sheet_name, label_old, label_new As String
Dim i As Integer
Dim sheetrng As Range
Set sheet_rng = Range(Sheets("Test").Range("B65536").End(xlUp), Range(Sheets("Test").Range("B5"))) 'all queries
'Set sheet_name = Range(Sheets("Test").Range("B65536").End(xlUp), Range(Sheets("Test").Range("B5"))) 'sheet name
'Set label_old = Range(Sheets("Test").Range("D65536").End(xlUp), Range(Sheets("Test").Range("D5"))) 'search term
'Set label_new = Range(Sheets("Test").Range("E65536").End(xlUp), Range(Sheets("Test").Range("E5"))) 'replacement
i = 0 'set counter to 0
For Each cell In sheet_rng
With ThisWorkbook.Sheets(cell.Value)
.Activate
.Cells.Find(What:=cell.Offset(0, 2).Value, After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
.ActiveCell.Replace What:=cell.Offset(0, 2), Replacement:=cell.Offset(0, 3), LookAt:=xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
End With
i = i + 1
Next
End Sub
I am running Office on MAC which I have been told is not great with VBA, but I sadly have no choice and appreciate all the help I can get.
Thank you
EDIT:
here a screenshot of my sample data
Note: my sheet name is in A, search value in C and replace value in D
Looks like your data is in B, D and E columns.
Following is the macro for A, C and D columns.
Sub FindReplaceMutiValMutiSheet()
Dim FRdata As Range, TempSh As Worksheet, TempData As Range, FRarr
LRow = Range("A" & Rows.Count).End(xlUp).Row
Set FRdata = Sheets("Sheet1").Range("A1:D" & LRow)
'Copy FRData to temporary sheet and assign it to TempData
Set TempSh = Sheets.Add(, Sheets(Sheets.Count))
TempSh.Range("A1").Resize(FRdata.Rows.Count, FRdata.Columns.Count).Value = FRdata.Value
Set TempData = TempSh.Range("A1:D" & LRow)
'Sort TempData on "Sheet Name" (A) and "Search" (C) Columns
With TempSh.Sort
.SortFields.Add2 Key:=Range(TempData(1, 1), TempData(TempData.Rows.Count, 1)) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SortFields.Add2 Key:=Range(TempData(1, 3), TempData(TempData.Rows.Count, 3)) _
, SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
.SetRange Range(TempData.Address)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
'Array of TempData Values
FRarr = TempData.Value
'Delete TempSh as no longer required.
Application.DisplayAlerts = False
TempSh.Delete
Application.DisplayAlerts = True
'Find and replace loop basded on FRarr array
For i = 2 To UBound(FRarr, 1)
If ActiveSheet.Name <> FRarr(i, 1) Then Sheets(FRarr(i, 1)).Activate
Range("A1").Activate
Cells.Replace What:=FRarr(i, 3), Replacement:=FRarr(i, 4), LookAt:= _
xlPart, SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Next
End Sub
Tested it on following sample data; works fine.
With below code I could sort data (marked with blue background) from 2 columns based on "B" column. Similarly I want to repeat the same for each blue block. I've highlighted cells manually just for illustration. Any help will be appreciated.
Code:
Sub SortRanges()
Dim firstcell As String
With Columns("B")
.Find(what:="*", after:=.Cells(1, 1), LookIn:=xlValues).Activate
firstcell = ActiveCell.Row
End With
Range(Selection, Selection.End(xlDown)).Select
Range(Selection, Selection.End(xlToLeft)).Select
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Sheet4").Sort.SortFields.Add Key:=Range("B" & firstcell & ":B" & firstcell + 5), _
SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Sheet4").Sort
.SetRange Range("A" & firstcell & ":B" & firstcell + 5)
.Header = xlGuess
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Try a loop down your column and, as it looks like everything is blocks of 5, do something like:
lr = cells(rows.count,1).end(xlup).row
For i = 1 to lr
if cells(i,1).interior.color = Blue Then `FIX THIS TO MATCH THE BLUE YOU WANT
Range(Cells(i,1),Cells(i+5,2)).Sort key1:=Range(Cells(i,2),Cells(i+5,2)), order1:=xlAscending, Header:=xlNo
i=i+5
End if
next i
I may have not understood the part about your highlighting... if that blue is the "highlight" then you can modify the above such that:
lr = cells(rows.count,1).end(xlup).row
For i = 1 to lr
if not isempty(cells(i,2)) Then
Range(Cells(i,1),Cells(i+5,2)).Sort key1:=Range(Cells(i,2),Cells(i+5,2)), order1:=xlAscending, Header:=xlNo
i=i+5
End if
next i
One more thing... if you can just run 2 sorts in sequence, second should be your final sort, like:
lr = cells(rows.count,1).end(xlup).row
For i = 1 to lr
if not isempty(cells(i,2)) Then
Range(Cells(i,1),Cells(i+5,2)).Sort key1:=Range(Cells(i,1),Cells(i+5,1)), order1:=xlAscending, Header:=xlNo
Range(Cells(i,1),Cells(i+5,2)).Sort key1:=Range(Cells(i,2),Cells(i+5,2)), order1:=xlAscending, Header:=xlNo
i=i+5
End if
next i
I am trying to implement a button that, when pressed sorts an array first alphabetically, then based on font color. The column that I am using to sort has 3 possible values (enrolled, waitlisted, and cancelled). The font color for 'cancelled' is grey. I want to get enrolled at the top of the list, then waitlisted, then cancelled at the bottom. Shouldn't be that difficult, but I can't get the code to work. Here's the code I wrote. Many thanks!
Private Sub btnSort_Click()
Dim SortArray As Range
Dim SortColumn As Range
Set SortArray = Range("A3").CurrentRegion
Set SortColumn = Range(Range("A3").End(xlToRight), Range("A3").End(xlToRight).End(xlDown))
SortArray.Sort Key1:=SortColumn, Header:=xlYes
With SortArray.Sort
.SortFields.Clear
.SortFields.Add Key:=SortColumn
.xlSortOnFontColor
.SortOnValue.Color = RGB(192, 192, 192)
.SortOrder = xlAscending
.Header = xlYes
.Apply
End With
Since there are only 3 values, we use a helper column and then assign values to it. We then sort and then finally delete the helper column.
Let's say, your data looks like this
Try this code. I have commneted the code so you should not have a problem in understanding it.
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, lCol As Long
Dim rng As Range
Dim ColName As String
'~~> Change this to the relevant sheet
Set ws = Sheet1
With ws
'~~> Insert a helper column in Col A
.Columns(1).Insert Shift:=xlToRight
.Cells(1, 1).Value = "TmpHeader"
'~~> Get Last Row and last Column
'~~> I am assuming that headers are in row 1
lRow = .Range("B" & .Rows.Count).End(xlUp).Row
lCol = .Cells(1, Columns.Count).End(xlToLeft).Column
ColName = Split(Cells(, lCol).Address, "$")(1)
'~~> Insert the formula in Col A
.Range("A2:A" & lRow).Formula = "=IF(RC[1]=""enrolled"",1,IF(RC[1]=""waitlisted"",2,3))"
'~~> Set your range
Set rng = .Range("A1:" & ColName & lRow)
'~~> Sort it
rng.Sort Key1:=.Range("A2"), Order1:=xlAscending, Header:=xlYes, _
OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
DataOption1:=xlSortNormal
'~~> Delete the helper column
.Columns(1).Delete
End With
End Sub
When you run the above code, it inserts a helper column and then inserts a formula =IF(B2="enrolled",1,IF(B2="waitlisted",2,3)) What this basically does is assigns a value of 1,2 and 3 based on the value whether it is enrolled, waitlisted or cancelled.
Once the formula is inserted, we sort on Col A in ascending order and then finally delete the helper column.
Figured it out:
ActiveSheet.Range("A3").CurrentRegion.Sort Key1:=Range("I3"), Header:=xlYes
ActiveSheet.Sort.SortFields.Clear
ActiveSheet.Sort.SortFields.Add(Range("I3"), _
xlSortOnFontColor, xlDescending, , _
xlSortNormal).SortOnValue.Color = RGB(192, 192, 192)
With ActiveSheet.Sort
.SetRange Range("A3").CurrentRegion
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
So I've got an incredibly large contact list, originally an export from Outlook so it follows the same formatting. I've an incredibly large number of duplicates down to records holding the same name, but separate addresses / mobile numbers.
I'm looking for a macro that can help me merge these duplicates so I don't lose things like different addresses under the same name.
http://i.stack.imgur.com/EaI6e.png
In this case I'd love a macro to see that A3 is a duplicate of A2, so take J3 to O3 and paste these in Q2 to V2. Then repeat this process for any duplicate pair found.
This is a bit rudimentary, but it works. Note, since you didn't say what should happen where there are more than 2 duplicates, this macro won't really work if that's the case.
Sub moveDuplicates()
Dim i As Integer, lastRow As Integer
Dim primaryRange As Range, copyToRange As Range, cel As Range, cel2 As Range, rng As Range
Dim ws As Worksheet
Set ws = ActiveSheet
'First, sort by "Key" to get duplicates all in a row
With ws.Sort
.SortFields.Clear
.SortFields.Add Key:=Range( _
"A2:A" & ws.UsedRange.Rows.Count), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
.SetRange Range("A1:P" & ws.UsedRange.Rows.Count)
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
lastRow = ws.UsedRange.Rows.Count
Set rng = ws.Range(ws.Cells(2, 1), ws.Cells(lastRow, 1))
Dim lastDupRow As Integer, startDupRow As Integer, copyRow As Integer
For Each cel In rng
'First, see if the cell has a duplicate anywhere, if not, then goto next cel
cel.Select
If WorksheetFunction.CountIf(rng, cel.Value) > 1 Then
Debug.Print "Duplicate exists"
'So, since we know a duplicate exists, we need to copy the duplicate rows' info.
startDupRow = cel.Row + 1
lastDupRow = ws.Columns(1).Find(cel.Value, searchDirection:=xlPrevious).Row
If lastDupRow - startDupRow = 0 Then
copyRow = lastDupRow
Else
End If
For Each cel2 In ws.Range(Cells(startDupRow, 1), ws.Cells(lastDupRow, 1))
' pasteRange(cel.Row).Select
' copyRange(cel2.Row).Select
pasteRange(cel.Row).Value = copyRange(cel2.Row).Value
copyRange(cel2.Row).EntireRow.Delete
Next cel2
End If
Next cel
End Sub
Private Function copyRange(ByVal iRow As Integer) As Range
Set copyRange = Range(Cells(iRow, 10), Cells(iRow, 15))
End Function
Private Function pasteRange(ByVal xRow As Integer) As Range
Set pasteRange = Range(Cells(xRow, 17), Cells(xRow, 22))
End Function
Hi i am writing a code in vb to check a particular value in a sheet, if the value is not available then it should go back to another sheet to take new value to find, if the value is found i have to do some operation on that sheet i have the below code to find the value in the sheet but if i pass the same in a DO WHILE loop as condition it gives a compile error
find vaue code
Selection.Find(What:=last_received, After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False).Activate
could some one please help me to write a code of DO WHILE with the above find in the loop condition so that if the condition gives false (i,e if the value is not found in the sheet) then i should use some other value to find
this is the code that i am going to put in loop
Sheets("Extract -prev").Select
Application.CutCopyMode = False
ActiveWorkbook.Worksheets("Extract -prev").Sort.SortFields.Clear 'sorting with tickets
ActiveWorkbook.Worksheets("Extract -prev").Sort.SortFields.Add Key:=Range( _
"C2:C2147"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
xlSortNormal
With ActiveWorkbook.Worksheets("Extract -prev").Sort
.SetRange Range("A1:AB2147")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
Application.Goto Reference:="R1C3" 'taking last received ticket
Selection.End(xlDown).Select
Selection.Copy
Sheets("Calc").Select
Application.Goto Reference:="Yesterday_last_received"
ActiveSheet.Paste
this code takes the last ticket but based on it's availablity in next sheet "extract" i have to take one ticket previous to the last one (and on).
Try below code :
Sub test()
Dim lastRow As Long
Dim rng As Range
Dim firstCell As String
lastRow = Sheets("sheet1").Range("A" & Rows.Count).End(xlUp).Row
For i = 1 To lastRow
Set rng = Sheets("sheet2").Range("A:A").Find(What:=Cells(i, 1), LookIn:=xlValues, lookAt:=xlPart, SearchOrder:=xlByRows)
If Not rng Is Nothing Then firstCell = rng.Address
Do While Not rng Is Nothing
rng.Offset(0, 1) = "found"
Set rng = Sheets("sheet2").Range("A:A").FindNext(rng)
If Not rng Is Nothing Then
If rng.Address = firstCell Then Exit Do
End If
Loop
Next
End Sub