Need to delete irrelevant rows in a spreadsheet - excel

Why does the following code not delete irrelevant rows in my spreadsheet?
Sub Macro1Format()
'
' Macro1Format Macro
'
Dim i As Integer
i = 0
Do While (Range("A1").Value <> "Project ID") And (i < 100)
Range("1:1").Delete
i = i + 1
Loop
End Sub

I'll take a stab that you would like something like:
Sub Macro1Format()
Dim i As Integer
i = 99
For i = 99 To 1 Step -1
If Range("A" & i).Value <> "Project ID" Then
Range(i & ":" & i).Delete
End If
Next
End Sub
You seem to have confused 1 with i but also when deleting rows it may be best to start from the bottom up since the row count changes as a consequence of any row deletion. There were also some syntax problems.

Related

Variable is reset to the value that is assigned before the loop

I must be overlooking something here, but after having overlooked it for an hour, it's time to get some help. This is my code:
For Each CurrentRow In Range(FullRange)
PhotoIndex = 1
For Each CurrentCell In CurrentRow
CurrentValue = CurrentCell.Value
If Not IsEmpty(CurrentValue) And CurrentValue <> "" Then
FileExtensionWithPeriod = Right(CurrentValue, Len(CurrentValue) - InStrRev(CurrentValue, ".") + 1)
If Len(FileExtensionWithPeriod) >= 4 And Len(FileExtensionWithPeriod) <= 5 Then
MsgBox ("before: " & PhotoIndex)
URLDownloadToFile 0, CurrentValue, FullFolderName & "\" & PhotoIndex & FileExtensionWithPeriod, 0, 0
PhotoIndex = PhotoIndex + 1
MsgBox ("after: " & PhotoIndex)
End If
End If
Next
Next
For each column I get MsgBoxes that state: "before: 1" and "after: 2". Why is PhotoIndex reset to 1 in the next iteration? The rows in the range all have at least 7 columns. If I add more MsgBoxes to inspect things like CurrentValue, I can see that the code loops over these columns. Yet, PhotoIndex is reset to 1 for each column, while that assignment is outside of the loop.
FYI: the full code has Dim statements for all used variables.
Rory's remark is the answer. Apparently the default looping through a range is column-wise, not row-wise. I am an experienced programmer, but VBA is something that I do rarely (last time was about 15 years ago, I think).
So, changing
For Each CurrentRow In Range(FullRange)
For Each CurrentCell In CurrentRow
into
For Each CurrentRow In Range(FullRange).Rows
For Each CurrentCell In CurrentRow.Cells
solves the problem.

Join rows based on unique ID

I have 32.000 rows with data. Some data are in a different place and I want to join them with something that I can apply to all rows and not manually. Each "group" have the same ID, in this example is "XPTO"
I have something like this now (but with more columns):
I want it to be like this:
The problem is that I need a clever way, because they are not always exactly like this example. Some of them have 10 rows with the same ID "XPTO" (example)
I am struggling with this =/ ty
Here's how I would approach this.
1) From your comment, I understand that the logic is positional (the first one on the left (Casteloes de) goes with the first one on the right (R Dr Antonio) for the matching value in column A. If that is true, then I would insert a column where you start numbering sequentially, then Fill Down to get sequential numbers all the way to the end. This will help preserve the positional logic if you need to sort or rearrange your data. It will also help you with the logic of "first match", "second match", etc.
2) My next step would be to separate the two sets of data into separate tables/tabs (with the sequentially numbered column appearing in each) and use INDEX/MATCH. The recent answer here will help you with how to increment the match: Is there such thing as a VLOOKUP that recognises repeated numbers?
3) Alternative - this may even be easier, although you'll want to do extensive data checking to make sure nothing got screwed up. With the two tables from step 2, sort by any column with data in it, then delete the blank rows from each table. Then, sort each by the sequentially numbered column to return to the original order. At that point you may be able to just copy and paste. Check carefully for errors if you do this.
I am positive that the solution above given by CriketBird work, at least it has a good logic to solve it, but since I am a newbie in excel, I couldn't figure it out how to solve it that way.
So I solved it by using VBA in excel...(maybe I went too far for this simple problem, but it was my only option).
I will leave the code here if someone want it for a similar situation. (just select the first column and row your table starts and hit run)
Function Area(medico As String) As Integer
Do While countOk < 1
If medico = ActiveCell.Value Then
ActiveCell.Offset(1, 0).Select
rowCount = rowCount + 1
Else: countOk = 1
End If
Loop
Area = rowCount
End Function
Sub Teste()
Dim PaginaMedico As String
Dim totalrowCount As Integer
Dim rowCount As Integer
Dim countOk As Integer
Dim right As Integer
Dim left As Integer
Dim listaleft As New Collection
Dim listaright As New Collection
rowCount = 1
rowOk = 0
totalrowCount = 0
right = 0
left = 0
Do While ActiveCell.Value <> 0
PaginaMedico = ActiveCell.Value
rowCount = Area(PaginaMedico)
totalrowCount = totalrowCount + rowCount
Range("A" & (totalrowCount - (rowCount - 1))).Select
For i = ((totalrowCount + 1) - rowCount) To totalrowCount
If IsEmpty(Range("E" & (i)).Value) And IsEmpty(Range("F" & (i)).Value) Then
Range("T" & (i)).Value = "Empty"
ElseIf Not IsEmpty(Range("E" & (i)).Value) And Not IsEmpty(Range("F" & (i)).Value) Then
Range("T" & (i)).Value = "Full"
ElseIf Not IsEmpty(Range("E" & (i)).Value) And IsEmpty(Range("F" & (i)).Value) Then
left = left + 1
listaleft.Add i
ElseIf IsEmpty(Range("E" & (i)).Value) And Not IsEmpty(Range("F" & (i)).Value) Then
right = right + 1
listaright.Add i
End If
Next i
If Not (right = left) Then
Range("T" & totalrowCount).Value = "BOSTA"
right = 0
left = 0
End If
If listaleft.Count = listaright.Count Then
For i = 1 To listaleft.Count
Range("F" & listaright(1) & ":" & "S" & listaright(1)).Cut Range("F" & listaleft(1) & ":" & "S" & listaleft(1))
listaright.Remove (1)
listaleft.Remove (1)
Next i
End If
Set listaleft = New Collection
Set listaright = New Collection
Range("A" & (totalrowCount + 1)).Select
Loop
End Sub

Find if two non-consecutive values are the same vba

I have one column of data with either "UP", "DOWN" or "" as values. I am trying to write code that states that for all rows, if the first cell is "UP" then check the next rows until I come to either "DOWN" or "UP", i.e. if the next row has a "" then check the next row until I come to either a "DOWN" or "UP".
I am very new to VBA, and have tried various options, but seem to only be able to bring back where there are consecutive "UP"s or "DOWNS" rather than where there is an "UP", a number of rows of "" and then another "UP".
This is my code:
Range("z1:z250").Select
Selection.ClearContents
For Row = 2 To 250
If Range("Y" & Row).Value = "UP" Then
For sRow = 3 To 250
If Range("Y" & Row + 1).Value = "UP" Then
Range("Z" & Row) = "MT-UP"
ElseIf Range("Y" & Row + 1).Value = "" Then
End If
Next
End If
Next
End Sub
I have tried to add code such as For Each c in Range (“Y3”:”Y250”) but this doesn't make it find the next UP, and makes it very slow. I have also tried GoTo next cell (although seem to understand this is frowned upon!) but this doesn't work either. Any help appreciated.
Not 100% clear if this is what you want but take a look...
Instead of nested loops I used a flag to mark when a second consecutive "UP" was found before encountering a "DOWN". From your description it seems there's no need to check for empty cells ("").
Sub MTTest()
Dim Row As Long
Dim MTRow As Long
Dim MTFlag As Boolean
Range("Z1:Z250").ClearContents
For Row = 2 To 250
If Range("Y" & Row).Value = "UP" Then
If MTFlag = True Then
Range("Z" & MTRow) = "MT-UP"
MTFlag = Flase
Else
MTFlag = True
MTRow = Row
End If
Else
If Range("Y" & Row).Value = "DOWN" Then MTFlag = False
End If
Next
End Sub

Issues counting strings in VBA Excel

Hi i am trying to create a macro that will loop through my worksheet and find a specific string of text. Once if has found that string i want it to look to the column next to it and if it says PoweredOn or PoweredOff then add 1 to a counter then display the number at the end.
in my excel i have column A as my virtual machines and in column B is the power state I have a loop setup to look for one virtual machine that is a template and is powered on but when i run my macro it prints it as 0 here is my code at the moment.
Dim POT As Integer
Dim POFFT As Integer
Sheets("tabvInfo").Select
Range("A2").Select
Do
If ActiveCell.Value = ("vCloud Cell Template") Then
If ActiveCell.Offset(0, 1).Value = ("PoweredOn") Then
POT = Selection.Cell.Count
Else
If ActiveCell.Offset(0, 1).Value = ("PoweredOff") Then
POFFT = Selection.Cell.Count
End If
End If
End If
ActiveCell.Offset(1, 0).Select
Loop Until IsEmpty(ActiveCell.Offset(1, 0))
MsgBox ("The number of powerered on VMs is " & POT)
MsgBox ("The number of powerered off VMs is " & POFFT)
Can anyone tell me why i am getting 0 as the result? I also need to make this look at other templates on my system while retaining the count of values would i need to create a do loop for each template or can i use an array to do this?
Try this instead
Sub Main()
Dim POT As Long
Dim POFFT As Long
Dim c As Range
For Each c In Sheets("tabvInfo").Range("A2:A" & Sheets("tabvInfo").Range("A" & Rows.Count).End(xlUp).Row)
If StrComp(c, "vCloud Cell Template", vbTextCompare) = 0 Then
If StrComp(c.Offset(0, 1), "PoweredOn", vbTextCompare) = 0 Then
POT = POT + 1
ElseIf StrComp(c.Offset(0, 1), "PoweredOff", vbTextCompare) = 0 Then
POFFT = POFFT + 1
End If
End If
Next
MsgBox ("The number of powerered on VMs is " & POT)
MsgBox ("The number of powerered off VMs is " & POFFT)
End Sub
It eliminates the .Select statement and .ActiveCell. It's a simple for loop that achieves what you want.
I am not sure you realize but you can achieve this using 2 very simple formulas for PoweredOn and Off
=COUNTIFS(A:A,"vCloud Cell Template",B:B, "PoweredOn")
=COUNTIFS(A:A,"vCloud Cell Template",B:B, "PoweredOFF")
Therefore to eliminate the need for using a loop you can
Sub NoLoop()
MsgBox "Powered ON: " & Evaluate("=COUNTIFS(A:A,""vCloud Cell Template"",B:B, ""PoweredOn"")")
MsgBox "Powered OFF: " & Evaluate("=COUNTIFS(A:A,""vCloud Cell Template"",B:B, ""PoweredOff"")")
End Sub

How to hide rows in VBA based on values in row, quickly

this is my first time using the site, so forgive me for any inept explaining. I have a working macro to hide/unhide rows based on content of the rows, I just want it to be faster. Using a check box, when the box is checked, all rows with an "x" in column D get unhidden, those without an "x" get hidden. Same thing happens when it is unchecked, except it references column C, not D.
Right now, this code works. It's just a little slower than I'd like, since I'm sharing this with a bunch of people. Any ideas for how to speed it up? I'm pretty darn new to VB (the internet is astoundingly wise and a good teacher), but that doesn't matter. I already improved the code - before it selected each row, then referenced the column, and it was awful. Any ideas to speed it up (preferably without moving the screen) would be great.
Thanks so much folks,
DS
Sub NewLuxCheck()
Dim x As Integer
NumRows = Range("A42", "A398").Rows.Count
Range("A42").Select
If ActiveSheet.Shapes("checkbox2").OLEFormat.Object.Value = 1 Then
For x = 42 To NumRows + 41 Step 1
If Worksheets("Base").Range("D" & x).Value = "x" Then
Worksheets("Base").Range(x & ":" & x).EntireRow.Hidden = False
Else
Worksheets("Base").Range(x & ":" & x).EntireRow.Hidden = True
End If
Next
Else
For x = 42 To NumRows + 41 Step 1
If Worksheets("Base").Range("C" & x).Value = "x" Then
Worksheets("Base").Range(x & ":" & x).EntireRow.Hidden = False
Else
Worksheets("Base").Range(x & ":" & x).EntireRow.Hidden = True
End If
Next
End If
MsgBox ("Done")
End Sub
You could use array formula and let Excel to return array with row-numbers where 'x' value occures. It will be quicker but you'll have to reorganise your code and create separate functions etc.
Here example where array formula finds rows whre in column 'D' the cell has value 'x'. Then string of this row numbers is created in form of "A1,A5,A10" ...means 'x' was found in rows 1,5,10. And finally Range(rowsJoind).EntireRow.Hidden is used for all the rows to be hidden/un-hidden in one step.
For rows with value different then 'x' you'll have to use formula like '=IF({0}<>""x"", ROW({0}), -1)'.
Sub test()
Dim inputRange As Range
Dim lastRow As Long
Dim myFormula As String
Dim rowsJoined As String, i As Long
Dim result As Variant
With Worksheets("Base")
lastRow = .Range("D" & .Rows.Count).End(xlUp).Row
Set inputRange = .Columns("D").Resize(lastRow)
Application.ReferenceStyle = xlR1C1
myFormula = "=IF({0}=""x"", ROW({0}), -1)"
myFormula = VBA.Strings.Replace(myFormula, "{0}", inputRange.Address(ReferenceStyle:=xlR1C1))
result = Application.Evaluate(myFormula)
result = Application.Transpose(result)
Application.ReferenceStyle = xlA1
For i = LBound(result) To UBound(result)
If (result(i) > -1) Then
rowsJoined = rowsJoined & "A" & result(i) & IIf(i < UBound(result), ",", "")
End If
Next i
.Range(rowsJoined).EntireRow.Hidden = False
End With
End Sub

Resources