How to distribute a known number evenly across a range in VBA - excel

I've a problem here, I've been trying to use VBA to distribute a known number evenly across a range.The problem is that I need to find the way where the numbers in the range be as equal as possible to each other, could you help me? or give ideas?
The data set is as follow
The known number is given by "TV Comodin" Row in color Red, and here is my try:
Sub Prueba()
Columns("A:A").Select
Set Cell = Selection.Find(What:="TV Comodín", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
ActiveCell = Cell
Cell.Select
comodin = ActiveCell.Offset(0, 1).Value2
Range("A2").Select
Firstrow = ActiveCell.Row
Selection.End(xlDown).Select
Lastrow = ActiveCell.Row
j = comodin
While (j > 0)
For i = 2 To Lastrow
Range("B2").Select
Range("B" & i) = Range("B" & i).Value + 1
If j > 0 Then j = j - 1
If j = 0 Then Exit For
Next
Wend
End Sub
Basically, my code finds the "TV Comodin" row to get de number of times that the loop is gonna add 1 by 1 in every single row of its column,
Sorry, I'm a little bit new on VBA, thanks by the way.

Here's one approach. Find the smallest number in the range: add one. Repeat until you've done that (eg) 55 times.
Sub Prueba()
Dim f As Range, ws As Worksheet, comodin As Long, rng As Range, m, mn
Set ws = ActiveSheet
Set rng = ws.Range("A2", ws.Range("A2").End(xlDown)).Offset(0, 1)
Set f = ws.Columns("A").Find(What:="TV Comodín", LookIn:=xlFormulas, _
LookAt:=xlWhole, MatchCase:=False)
If Not f Is Nothing Then
rng.Value = ws.Evaluate("=" & rng.Address() & "*1") 'fill empty cells with zeros
comodin = f.Offset(0, 1).Value
Do While comodin > 0
mn = Application.Min(rng)
If mn >= 100 Then Exit Do ' exit when no values are <100
m = Application.Match(mn, rng, 0)
rng.Cells(m).Value = rng.Cells(m).Value + 1
comodin = comodin - 1
Loop
Else
MsgBox "not found!"
End If
End Sub

Related

Pasting into next empty row

Im trying to create a code that will find a particular word on a page and then copy and paste all the cells underneath until a blank cell in another workbook. The only issue i'm finding is that the data shifts when i run it again and there is supposed to be a blank cell.
Sub CopyRows()
Dim Found As Range
Dim ANextFreeCell As Range
Dim BNextFreeCell As Range
Dim wkDest As Worksheet
Set wsDest = Workbooks("sample_bills (version 1).xlsx").Worksheets("sample_bills")
Set Found = Cells.Find(What:="Description", LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False)
If Found Is Nothing Then
MsgBox "ERROR"
Else
i = Found.Row
j = Found.Column
End If
Do
Set ANextFreeCell = wsDest.Cells(Rows.Count, "C").End(xlUp).Offset(RowOffset:=1)
Set BNextFreeCell = wsDest.Cells(Rows.Count, "D").End(xlUp).Offset(RowOffset:=1)
ANextFreeCell = Cells(i + 1, j)
BNextFreeCell = Cells(i + 1, j + 1)
i = i + 1
Loop Until IsEmpty(Cells(i, j)) And IsEmpty(Cells(i, j + 1))
End Sub
Any help would be greatly appreciated :)
To find the last row for multiple columns, use Range("C:D").Find, add 1 to get the next empty row.
NextEmptyRow = ActiveSheet.Range("C:D").Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row + 1
and then paste using...
ActiveSheet.Cells(NextEmptyRow, "C")

Function to find all matches of a value

I need your help.
Sorry, I am really new to VBA but, how do I go about converting or adding onto the Excel function below to loop through all the found matches. Right now it only returns 1 match but i'd like to to have it modified to return all occurrences of a match so that I can input it into my userform for processing later.
Private Sub Search_Click()
With Sheet1
Set foundCell = .Cells.find(What:="test", After:=.Cells(1, 1), _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
End With
If Not foundCell Is Nothing Then
MsgBox ("""Match"" found in row " & foundCell.Row)
form1.location.Value = Cells(foundCell.Row, 1).Value
Else
MsgBox ("No match not found")
End If
End Sub
You can try findnext or add some small edits like something along these lines, just a continuous loop until you run out of matches
Private Sub Search_Click()
Dim rowNum As Long: rowNum = 1
Dim colNum As Long: colNum = 1
Do While ( True )
With Sheet1
Set foundCell = .Cells.find(What:="test", After:=.Cells(rowNum, colNum), _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
End With
If Not foundCell Is Nothing Then
MsgBox ("""Match"" found in row " & foundCell.Row)
form1.location.Value = form1.location.Value & vbCrLf & Cells(foundCell.Row, 1).Value
if foundCell.Row < rowNum Then Exit Do
rowNum = foundCell.Row
colNum = foundCell.Column
Else
If rowNum = 1 Then MsgBox ("No matches found")
Exit Do
End If
Loop
End Sub
Just in case you need to store data for all cells that contained your search item, you could use the following. Usage: myArray = makeArrayFoundCellInfoInRange("test", Sheets.("Sheet1").Range("A1:Z500"))
'**************************************************************************************************************************************************************
'To return an array of information (value, formula, address, row, and column) for all the cells from a specified Range that have the searched item as value
'Returns an empty array if there is an error or no data
'**************************************************************************************************************************************************************
Public Function makeArrayFoundCellInfoInRange(ByVal itemSearched As Variant, ByVal aRange As Variant) As Variant
Dim cell As Range, tmpArr As Variant, x As Long
tmpArr = Array()
If TypeName(aRange) = "Range" Then
x = 0
For Each cell In aRange
If itemSearched = cell.Value Then
If x = 0 Then
ReDim tmpArr(0 To 0, 0 To 4)
Else
tmpArr = reDimPreserve(tmpArr, UBound(tmpArr, 1) + 1, UBound(tmpArr, 2))
End If
tmpArr(x, 0) = cell.Value
tmpArr(x, 1) = cell.Formula
tmpArr(x, 2) = cell.Address(0, 0) 'Without the dollar signs
tmpArr(x, 3) = cell.Row
tmpArr(x, 4) = cell.Column
x = x + 1
End If
Next cell
End If
makeArrayFoundCellInfoInRange = tmpArr
Erase tmpArr
End Function

Identify range in an Excel outline group

I have an Excel sheet that has data grouped using the outline method.
I'm having issues defining a range from the beginning of the group to the end of the group.
I have this data populating a listbox in a userform.
If a user selected any item in this group to delete I need to remove the whole group.
I think I am over thinking it but is there a good way to define this range?
Here is a sample of what I am starting with below
`Sub delrows()
Dim StartRow As Integer
Dim EndRow As Integer
'if outline level should never drop below 2.
'If it is 2 then this will always be the beginning of the range.
If ActiveCell.Rows.OutlineLevel = 2 Then
y = ActiveCell.Row
Else
y = ActiveCell.Row + 3
'y= needs to look up until it see a 2 then go back down 1 row
End If
If ActiveCell.Rows.OutlineLevel <> 2 Then
x = ActiveCell.Row + 1
'x = needs to look down until it finds next row 2 then back up 1 row
Else
x = ActiveCell.Row
End If
StartRow = y
EndRow = x
Rows(StartRow & ":" & EndRow).Select '.Delete
End Sub`
Worked on it a little bit. Have the outline level stored as a value on the sheet in column AA.
Sub delrows()
Dim StartRow As Integer
Dim EndRow As Integer
Dim Rng As Range
Dim C As Range
Dim B As Range
'if outline level shoudl never drop below 2.
'If it is 2 then this will always be the begining of the range.
If ActiveCell.Rows.outlinelevel = 2 Then
'If ActiveCell = 2 Then
y = ActiveCell.Row
Else
Set Rng = Range("AA:AA")
Set B = Rng.Find(What:="2", After:=ActiveCell,LookIn:=xlFormulas,LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlPrevious, MatchCase:=False, SearchFormat:=False)
y = B.Offset(0, 0).Row
End If
If ActiveCell.Rows.outlinelevel <> 2 Then
Set Rng = Range("AA:AA")
Set C = Rng.Find(What:="2", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
x = C.Offset(-1, 0).Row
Else
If ActiveCell.Rows + 1 = 3 Then
Set Rng = Range("AA:AA")
Set C = Rng.Find(What:="2", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
x = C.Offset(-1, 0).Row
Else
x = ActiveCell.Row
End If
End If
StartRow = y
EndRow = x
Rows(StartRow & ":" & EndRow).Delete
End Sub
Try this:
Option Explicit
Public Sub RemoveGroup()
Dim grpStart As Range, grpEnd As Range, lvl As Long
Set grpStart = Sheet1.Range("A7").EntireRow 'test cell - A7
Set grpEnd = grpStart
lvl = grpStart.OutlineLevel
While lvl = grpStart.OutlineLevel 'find start of current group (up)
Set grpStart = grpStart.Offset(-1)
Wend
Set grpStart = grpStart.Offset(1) 'exclude 1st row in next group
While lvl = grpEnd.OutlineLevel 'find end of current group (down)
Set grpEnd = grpEnd.Offset(1)
Wend
Set grpEnd = grpEnd.Offset(-1) 'exclude 1st row in next group
With Sheet1.Rows(grpStart.Row & ":" & grpEnd.Row)
.ClearOutline
.Delete
End With
End Sub
Before and After:

EXCEL: highlighting reoccuring data in the same column

I have a column(D) of data in Excel that has been sorted using:
=TEXT(B2,"###").
This is to show a list of data (numberical) that has an additional "REP 1" against it.
Not all data has a "REP 1" in there, so I would like to highlight all fields which contain BOTH the number and the "REP 1".
I could highlight all "REP 1" fields, and see if there is a duplicate before it, but this is just a sample sheet. I have over 8,000+ fields to go through, and would be too time consuming.
Please see the below link for the example:
Required Formatting
I hope this all makes sense.
Thanks,
Tim.
Not sure if its possible to do with conditional formatting but this VBA code should work. Your Data wouldn't have to be sorted in any particular order, and assumes the data you are formatting is in column D. I've tested on a few 100 rows and it works fine, so should be fine with a large data set. Ive tried to explain what the code is doing through the comments in the code.
Sub formatCells()
Dim x As Variant
Dim y As Variant
Dim searchval As String
Dim a As Variant
Dim lastrow As Long
Dim rng As Range
Application.ScreenUpdating = False ' turn off screen updates
lastrow = Cells(Rows.Count, 4).End(xlUp).Row 'find the last blank cell
x = 2 'set rownumber
y = 4 'set columnnumber
While Cells(x, y) <> "" ' create loop
If InStr(Cells(x, y), "REP1") Then 'search for string in cell
Cells(x, y).Interior.Color = RGB(255, 0, 0) 'if string exists fill cell
End If
x = x + 1 ' loop
Wend ' end loop
x = 2 ' reset row number
y = 4 ' reset column number
While Cells(x, y) <> "" ' create loop 2
If Cells(x, y).Interior.Color = RGB(255, 0, 0) And InStr(Cells(x, y), "REP1") Then 'if cells is red and contains Rep1
a = Cells(x, y).Value ' set a to equal the cell that is red and and contains REP1
searchval = Left(a, Len(a) - 5) 'remove space and REP1 and set value ready for search
If searchval <> "" Then 'if theres a search value available run steps below
With Range("D1:D" & lastrow) 'set range to be column A
Set rng = .Find(What:=searchval, _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not rng Is Nothing Then 'If search value is found
Application.Goto rng, True ' go to cell
ActiveCell.Interior.Color = RGB(255, 0, 0) 'set cell to red
End If
End With
End If
End If
x = x + 1 'loop 2
Wend ' end loop 2
End Sub
EDIT - Looks at column B not D
Sub formatCells()
Dim x As Variant
Dim y As Variant
Dim searchval As String
Dim a As Variant
Dim lastrow As Long
Dim rng As Range
Application.ScreenUpdating = False ' turn off screen updates
lastrow = Cells(Rows.Count, 2).End(xlUp).Row 'find the last blank cell
x = 2 'set rownumber
y = 2 'set columnnumber
While Cells(x, y) <> "" ' create loop
If InStr(Cells(x, y), "REP1") Then 'search for string in cell
Cells(x, y).Interior.Color = RGB(255, 0, 0) 'if string exists fill cell
End If
x = x + 1 ' loop
Wend ' end loop
x = 2 ' reset row number
y = 2 ' reset column number
While Cells(x, y) <> "" ' create loop 2
If Cells(x, y).Interior.Color = RGB(255, 0, 0) And InStr(Cells(x, y), "REP1") Then 'if cells is red and contains Rep1
a = Cells(x, y).Value ' set a to equal the cell that is red and and contains REP1
searchval = Left(a, Len(a) - 5) 'remove space and REP1 and set value ready for search
If searchval <> "" Then 'if theres a search value available run steps below
With Range("B1:B" & lastrow) 'set range to be column A
Set rng = .Find(What:=searchval, _
After:=.Cells(1), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False)
If Not rng Is Nothing Then 'If search value is found
Application.Goto rng, True ' go to cell
ActiveCell.Interior.Color = RGB(255, 0, 0) 'set cell to red
End If
End With
End If
End If
x = x + 1 'loop 2
Wend ' end loop 2
End Sub

Excel: move the contents of the row to a specific column based on condition

I have a large excel file with consistent columns but they're not placed too accurately;
The example in the photo is illustrative to my problem; I'm only interested in the information after the "country" column.
Therefore, within each row, I would like to
1. check each row to find a specific string of characters - in this case "Spain".
2. move the row so that the cells with the strings found are all on the same column.
In the example below, all the rows should be moved so that "Spain" is under column F - arranging the rest of the info with it.
If word Spain isn't changed, use this VBA code:
Sub MoveCoun()
Dim LastRow As Long
Dim rFind As Range
Dim r As String
Dim m As Integer
LastRow = 1000
For n = 1 To LastRow
r = n & ":" & n
Range(r).Select
With Range(r)
Set rFind = .Find(What:="Spain", LookAt:=xlWhole, MatchCase:=False, SearchFormat:=False)
If Not rFind Is Nothing Then
If rFind.Column < 6 Then
m = 6 - rFind.Column
Range(Cells(n, 1), Cells(n, m)).Insert Shift:=xlToRight
ElseIf rFind.Column > 6 Then
m = rFind.Column - 6
Range(Cells(n, 1), Cells(n, m)).Delete Shift:=xlToLeft
End If
End If
End With
Next
End Sub

Resources