Deleting entire row whose column contains a 0, Excel 2007 VBA - excel

UPDATE:
Alright, so i used the following code and it does what i need it to do, i.e check if the value is 0 and if its is, then delete the entire row. However i want to do this to multiple worksheets inside one workbook, one at a time. What the following code is doing is that it removes the zeros only from the current spreadsheet which is active by default when you open excel through the VBA script. here the working zero removal code:
Dim wsDCCTabA As Excel.Worksheet
Dim wsTempGtoS As Excel.Worksheet
Set wsDCCTabA = wbDCC.Worksheets("Login")
Set wsTempGtoS = wbCalc.Worksheets("All_TemporaryDifferences")
Dim LastRow As Long, n As Long
LastRow = wsTempGtoS.Range("E65536").End(xlUp).Row
For n = LastRow To 1 Step -1
If Cells(n, 5).Value = 0 Then
Cells(n, 5).EntireRow.Delete
End If
Next
What am i doing wrong? when i do the same thing for another worksheet inside the same workbook it doesnt do anything. I am using the following code to remove zeros from anohter worksheet:
Set wsPermGtoS = wbCalc.Worksheets("All_PermanentDifferences")
'delete rows with 0 description
Dim LastRow As Long, n As Long
LastRow = wsPermGtoS.Range("E65536").End(xlUp).Row
For n = LastRow To 1 Step -1
If Cells(n, 5).Value = 0 Then
Cells(n, 5).EntireRow.Delete
End If
Next
Any thoughts? or another way of doing the same thing?
ORIGINAL QUESTION:
I want to delete all the rows which have a zero in a particular column. I am using the following code but nothing seems to happen:
CurrRow = (Range("E65536").End(xlUp).Row)
For Count = StartRow To CurrRow
If wsDCCTabA.Range("E" & Count).Value = "0" Then
wsDCCTabA.Rows(Count).Delete
End If
Next
StartRow contains the starting row value
CurrRow contains the row value of the last used row

See if this helps:
Sub DelSomeRows()
Dim colNo As Long: colNo = 5 ' hardcoded to look in col 5
Dim ws As Worksheet: Set ws = ActiveSheet ' on the active sheet
Dim rgCol As Range
Set rgCol = ws.Columns(colNo) ' full col range (huge)
Set rgCol = Application.Intersect(ws.UsedRange, rgCol) ' shrink to nec size
Dim rgZeroCells As Range ' range to hold all the "0" cells (union of disjoint cells)
Dim rgCell As Range ' single cell to iterate
For Each rgCell In rgCol.Cells
If Not IsError(rgCell) Then
If rgCell.Value = "0" Then
If rgZeroCells Is Nothing Then
Set rgZeroCells = rgCell ' found 1st one, assign
Else
Set rgZeroCells = Union(rgZeroCells, rgCell) ' found another, append
End If
End If
End If
Next rgCell
If Not rgZeroCells Is Nothing Then
rgZeroCells.EntireRow.Delete ' deletes all the target rows at once
End If
End Sub

Once you delete a row, u need to minus the "Count" variable
CurrRow = (Range("E65536").End(xlUp).Row)
For Count = StartRow To CurrRow
If wsDCCTabA.Range("E" & Count).Value = "0" Then
wsDCCTabA.Rows(Count).Delete
' Add this line:
Count = Count - 1
End If
Next

I got it. For future reference, i used
ActiveWorkbook.Sheets("All_temporaryDifferences").Activate
and
ActiveWorkbook.Sheets("All_Permanentdifferences").Activate

You don't need to use ActiveWorkbook.Sheets("All_temporaryDifferences").Activate. In fact if the ActiveWorkbook is different from wbCalc you would get an error.
Your real problem is that you are using an unqualified reference to Cells(n, 5).Value. Unqualified means that you aren't specifying which sheet to use so it defaults to the active sheet. That may work sometimes but it is poor code. In your case it didn't work.
Instead you should always use qualified references. wsTempGtoS.Cells(n, 5).Value is a qualified reference. wsTempGtoS specifies which worksheet you want so VBA is not left guessing.
Dim LastRow As Long, n As Long
LastRow = wsTempGtoS.Range("E65536").End(xlUp).Row
For n = LastRow To 1 Step -1
If wsTempGtoS.Cells(n, 5).Value = 0 Then
wsTempGtoS.Cells(n, 5).EntireRow.Delete
End If
Next
This: CurrRow = (Range("E65536").End(xlUp).Row) is also an unqualified reference. Instead it should be CurrRow = wsDCCTabA.Range("E65536").End(xlUp).Row.

Related

Excel VBA ListBox in User Form Populate data from Sheet Range, add row by row after evaluating for a condition

I am trying to write a VBA code where I want to populate DATA from a worksheet Range A to AQ spanning over multiple Rows. AQ contains Value "Open" or "Closed". I want to get the rows where AQ value is closed. I tried using the AutoFilter. This is working fine to an extent. But I have to use 2 For loops. One for Each Row and another for Each Column to populate Row wise, column by column into the list box
My Code as follows:
Note : Actual contents start from 6th Row where 6 contains the headers and data starts from 7th Row
Dim i As Long
Dim rowRange As Range
Dim AllData(1 To 1000, 1 To 43) As String
lstRecords.ColumnCount = 43
Set shDSR = mydata1.Sheets("DSR")
last_Row = shDSR.Cells(Rows.Count, 1).End(xlUp).Row
shDSR.AutoFilterMode = False
shDSR.Range("A6:AQ" & last_Row).AutoFilter Field:=43, Criteria1:="CLOSED"
Set rng = shDSR.Range("A6:AQ" & last_Row).SpecialCells(xlCellTypeVisible)
Dim filtrRow() As String
Dim rowCnt As Long
'Me.lstRecords.Clear
rowCnt = 0
If rng.Count > 0 Then
Me.lstRecords.Clear
Me.lstRecords.ColumnCount = rng.Columns.Count
For Each Row In rng.Rows
Me.lstRecords.AddItem
rowCnt = rowCnt +1
filterRow = Range(Row.Address)
'Me.lstRecords.List() = filterRow ''This throws error Type Mismatch so not using
For i = 1 To Row.Columns.Count
AllData(rowCnt, i) = Row.Cells(1, i).Value ''Move to Array
Me.lstRecords.List(rowCnt - 1, i - 1) = filterRow(1, i)'Buggy error when i = 11
Next
Next
'' Following segment works. Add data to Array and then populate ListBox from Array
Me.lstRecords.List() = AllData
Else
MsgBox "No data matches the filter criteria."
End If
Above Code has both approaches
a) Trying to load directly from excel Range (actually using filterRow, but can also directly use range with same issue). But, this approach stops always when i=11 with Invalid property error. I tried changing the data contents etc still same issue
Another Issue when Not taking the array based approach, only one line is added, so in affect only last line is available in the list box
b) Using the AllData array. I load all the row data (matching criteria) into the array and finally populate the listbox from array. THIS WORKS. But I do not like this approach
Can some one please point out where it is going wrong.
Thanks in advance
Problem is that filters create a non contiguous range consisting of areas which you have to iterate separately.
Option Explicit
Sub demo()
Dim mydata1 As Workbook, shDSR As Worksheet
Dim rng As Range, a As Range, r As Range
Dim last_row As Long, n As Long
Dim i As Long, rowCnt As Long
Dim ListData() As String
' change this
Set mydata1 = ThisWorkbook
Set shDSR = mydata1.Sheets("DSR")
With shDSR
.AutoFilterMode = False
last_row = .Cells(.Rows.Count, "AQ").End(xlUp).Row
.Range("A6:AQ" & last_row).AutoFilter Field:=43, Criteria1:="CLOSED"
Set rng = .Range("A6:AQ" & last_row).SpecialCells(xlCellTypeVisible)
.AutoFilterMode = False
End With
' clear listbox
With Me.lstRecords
.Clear
.ColumnCount = rng.Columns.Count
End With
'iterate areas and rows to count visible rows
For Each a In rng.Areas
n = n + a.Rows.Count
Next
rowCnt = 0
If n > 1 Then
' size array
ReDim ListData(1 To n, 1 To rng.Columns.Count)
' fill array
For Each a In rng.Areas
For Each r In a.Rows
rowCnt = rowCnt + 1
For i = 1 To UBound(ListData, 2)
ListData(rowCnt, i) = r.Cells(1, i).Value ''Move to Array
Next
Next
Next
' populate ListBox from Array
Me.lstRecords.List() = ListData
Else
MsgBox "No data matches the filter criteria."
End If
End Sub

Excel - VBA Insert Data From Raw File to Output File

Would like to ask if it is possible to create a condition in excel vba for inserting rows of matched values in output file
for example:
This is an example list of my student:
This one is for the checklist of their exams / questionnaires:
This would be the final output:
Is it possible for VBA to look like in the results file? I only figured out how to put the number series per TestLEVEL value. But still thinking how to insert the Questionnaire and Value columns exactly the way I want.
THANKS! hope it is possible
Upon further reflection, and assuming I have understood your requirements correctly, I think the easiest way to do this is by using the FILTER-function. Note that this function is only available in Office 365, and that your argument separator might be a different one than mine.
It is also not ideal for automating the task since I assume the number of Questionnaire / Value pairs will be different from time to time. It is fairly simple to use though, so I guess it won't be a lot of work to create the formulas.
The way I did it was creating a duplicate of the second sheet you have a picture of into my workbook, and then create a sheet similar to the third one you have a picture of. In this sheet I put the formula
=FILTER(Sheet1!$C$2:$C$19;Sheet1!$A$2:$A$19=D2;NA())
into cell F2 and
=FILTER(Sheet1!$D$2:$D$19;Sheet1!$A$2:$A$19=D2;NA())
into G2.
The formula then fills the filtered range into the column as shown below:
To get the Questionnaire values of the student with student no. 4321 into range F8:F13, use the formula
=FILTER(Sheet1!$C$2:$C$19;Sheet1!$A$2:$A$19=D8;NA())
and so on.
I think this should solve your problem as presented in the question, at least, though your sheet will probably need a bit of editing if you have different input data.
As a further tip, I would recommend changing your data to tables when that is what they basically are anyway, it makes referencing them a bit simpler.
I hope this was of some help to you, don't hesitate to ask if something seems unclear.
Use Find and FindNext to match the Student No and Test Levels on the 2 sheets.
Option Explicit
Sub MyMacro()
Dim wb As Workbook
Dim wsName As Worksheet, wsExam As Worksheet, wsOut As Worksheet
Dim rng As Range, rngNo As Range
Dim iLastRow As Long, r As Long, rOut As Long
Dim n As Integer, m As Integer, i As Long
Dim sNo As String, sTest As String, sFirstFind As String
Set wb = ThisWorkbook
Set wsName = wb.Sheets("Sheet1")
Set wsExam = wb.Sheets("Sheet2")
Set rngNo = wsExam.UsedRange.Columns("A:A") ' student no
Set wsOut = wb.Sheets("Sheet3")
wsOut.Cells.Clear
i = 1 ' col A no
n = 0 ' block row for Col B-F
m = 0 ' block row for Col G-H
rOut = 2
iLastRow = wsName.Cells(Rows.Count, "A").End(xlUp).Row
For r = 2 To iLastRow
sTest = wsName.Cells(r, "D")
sNo = wsName.Cells(r, "C")
' start new block if no or test different to previous row
If sNo <> wsName.Cells(r - 1, "C") _
Or sTest <> wsName.Cells(r - 1, "D") Then
' align columns
If m > n Then
rOut = rOut + m
Else
rOut = rOut + n
End If
n = 0
m = 0
' start new test
sTest = wsName.Cells(r, "D")
If sTest <> wsName.Cells(r - 1, "D") Then
wsOut.Cells(rOut, "A") = i
i = i + 1
End If
' search for matching Student No
Set rng = rngNo.Find(sNo, LookIn:=xlValues, lookat:=xlWhole)
If rng Is Nothing Then
Else
sFirstFind = rng.Address
Do
'is testlevel the same
If rng.Offset(0, 4) = sTest Then
' copy col C-D to G-H
rng.Offset(0, 2).Resize(1, 2).Copy wsOut.Cells(rOut + m, "G")
m = m + 1
End If
' find next
Set rng = rngNo.FindNext(rng)
Loop While Not rng Is Nothing And rng.Address <> sFirstFind
End If
End If
' copy col A-E to col B-F
wsName.Cells(r, "A").Resize(1, 5).Copy wsOut.Cells(rOut + n, "B")
n = n + 1
Next
MsgBox "Done", vbInformation
End Sub

VBA Add rows based on how many times a criteria is met

I am quite new to VBA so my question may sound silly to some of you.
I have a problem with my code. I am trying to check between 2 sheets(1st: test and 2nd: test data. In the code I am using the code name of the sheets) how may times a criteria/my product is met and based on that number to add that many rows beneath the SKU/product.
What I want to do is, if for my first product/SKU I have stock in 5 different locations, I want to add 5 rows in the first sheet and to see the qty in column D and the location in column E.
TestData tab
The reason why I need to list the quantity in different cells is that the stock is in different locations, so I can not just add in to one cell.
I am also adding screen shots of how my two sheets look like.
I have not add the loop to find the location yet, but I want to understand how to add the rows first.
Sub test()
Dim myrange As Range, testrange As Range, cell As Range, result As Range
Dim i As Long, testlastrow As Long, lastrow As Long
Dim helprng As Range
lastrow = TESTTAB.Range("a" & Rows.Count).End(xlUp).row
testlastrow = TDATA.Range("a" & Rows.Count).End(xlUp).row
Set testrange = TDATA.Range("a2:c" & testlastrow)
Set myrange = TESTTAB.Range("b2:b" & lastrow)
Set result = TESTTAB.Range("d2:e" & testlastrow)
Set helprng = TESTTAB.Range("f2:f" & lastrow)
For Each cell In myrange
For i = 1 To lastrow
If cell.Cells(i, 1) = testrange.Cells(i, 1) Then
result.Cells(i, 1) = testrange.Cells(i, 2)
End If
Next i
Next cell
End Sub
Here is the raw structure you were asking for.
Sub test()
' 011
Dim Rng As Range
Dim Tmp As Variant
Dim Radd As Long ' number of rows to add
Dim R As Long ' row counter
With Tdata
' Range, Cells and Rows Count, all in the same sheet
' exclude caption row(s)
Set Rng = .Range(.Cells(2, "A"), .Cells(.Rows.Count, "A").End(xlUp))
End With
Application.ScreenUpdating = False ' speed up the process
With TestTab
' end the loop in row 2 because row 1 might contain captions
' loop bottom to top because row numbers will change
' below the current row as you insert rwos
' column 1 = "A"
For R = .Cells(.Rows.Count, 1).End(xlUp).Row To 2 Step -1
Tmp = .Cells(R, 1).Value
Radd = Application.CountIf(Rng, Tmp)
If Radd > 1 Then
.Range(.Rows(R + 1), .Rows(R + Radd)).Insert
.Cells(R + 1, 1).Value = Radd ' for testing purposes
End If
Next R
End With
Application.ScreenUpdating = True ' now you look
End Sub
As our Evil Blue Monkey has suggested, inserting blank rows and then populating them may not be the most efficient way. You can copy a row and then click Insert to insert the copied data into a new row. Get the syntax from the Macro recorder if it's of interest. It works with the Range object the same way.

can someone help me make this formula work on an entire column?

im hoping that someone can help me to take a macro down an entire column.here is what i am trying to do.
the following table is in a worksheet called barcode. it is my master list. column E:E, is a helper column that has part numbers with countif numbers attach like so=:1,:2,:3, etc. i did this because i have multiple orders for part numbers that are due on different dates in the order report. in column c, there is a number of how many of a part has been ran. in column d, the number of parts that have been scrapped and would have to be ran again. i have highlighted a row to use as an example. in this case. part number ms-100 has a total of 1 part ran and zero scrapped.
the next sheet is my order report sheet. it displays what a customer has ordered of what part. the calculation that i want to have is: if ms-100:1 on the order report matches what is on the master list, then take the qty from the order report and subtract how many were ran, and add how many were scrapped. so for this case. if ms-100:1 =ms-100:1 then cell f8 =12-1+0.
my current code will do that, but it will only do the cells that i point them to and not the entire column. to make it easier to see if this code works or not, instead of changing the values of column f on the order report, i moved it to column l. the goal is to have the value change in f, but for now i was putting the value in l. as you can see, in L7, it says no order. i hope this clarifies what i am trying to accomplish. thank you very much. here is the code that i have so far. i was attempting to use for each cell but it doesnt seem to be working.
Sub FIND_MATCHES()
Dim sh1 As Worksheet
Dim sh4 As Worksheet
Set sh1 = ActiveWorkbook.Sheets("BARCODE")
Set sh4 = ActiveWorkbook.Sheets("ORDER REPORT")
Dim CELL As Range
Dim LASTROW As Long
Dim R As Long
Dim c As Range
Set c = sh4.Range("L:L")
LASTROW = sh4.CELLS(Rows.COUNT, 12).End(xlDown).Row
'LASTROW = Range("F7:F" & Rows.COUNT).End(xlUp).Row
Dim COMPID As Range
Set COMPID = sh1.Range("E:E").Find(What:=sh4.Range("N7").Value, LookIn:=xlValues, LOOKAT:=xlWhole)
'sh4.Range("L7:L" & LASTROW).Activate
'sh4.Range("L7:L" & LASTROW).Select
For Each CELL In c
If COMPID Is Nothing Then
sh4.Range("L7").Value = "NO ORDER"
Else
'TEST CELL'sh4.Range("L7").Value = COMPID.Offset(, -2).Value
sh4.Range("L7").Value = sh4.Range("F7").Value - COMPID.Offset(0, -2).Value + COMPID.Offset(0, -1).Value
'Range("L7:L" & LASTROW).Select
' Range("L8").Select
Exit For
End If
Next CELL
End Sub
I was able to find the solution myself. the below code is what i used. I thought i would share it just in case someone else had the same issue.
Sub FIND_MATCHES()
Dim barcode As Worksheet
Dim order As Worksheet
Set barcode = ActiveWorkbook.Sheets("BARCODE")
Set order = ActiveWorkbook.Sheets("ORDER REPORT")
Dim LASTROW As Long
Dim c As Long
Dim X As Integer
X = 1
Dim finalrow As String
finalrow = order.cells(Rows.COUNT, 12).End(xlUp).Row
Dim location As Range
Set location = barcode.cells.Item(X, "E")
Dim HELPER As String
Dim NUMROWS As String
NUMROWS = order.cells(Rows.COUNT, 14).End(xlUp).Row
HELPER = barcode.cells.Item(X, "E").Value
LASTROW = order.cells(Rows.COUNT, 14).End(xlUp).Row
Dim ENDROW As String
ENDROW = order.cells(Rows.COUNT, 4).End(xlUp).Row
For X = 1 To ENDROW
For c = 7 To NUMROWS
If order.cells(c, 14).Value = barcode.cells.Item(X, "E").Value Then
order.cells(c, 12).Value = order.cells(c, 6).Value - barcode.cells.Item(X, "E").OFFSET(0, -2).Value + barcode.cells.Item(X, "E").OFFSET(0, -1).Value
Else
ActiveCell.OFFSET(1, 0).Select
End If
Next c
Next X
order.Range("A2").Select
End Sub

How to copy range from multiple sheets to one sheet (one range under another) if a condition is met?

I have and excel workbook with multiple sheets and I need a range from each one to be copied into one "Main" sheet (one under another) if a condition is met.
Each sheet is different and the number of rows and cells may vary.
In all of the sheets (except the main sheet which is blank) cell B1 is a check cell that contains "yes" or is blank.
If cell B1 ="yes" the macro must migrate the range (from row 2 to the lat filled in row) into the main sheet.
The selected ranges must be copied one under another in the main sheet (so that it's like a list)
I am still a beginner in VBA and if anyone could help me a little with the code I would very much appreciate it :).
I tried to build in the code using "For Each - Next" but perhaps it would be better to make it with a Loop cicle or something else.
Sub Migrate_Sheets()
Dim wksh As Worksheet, DB_range As Range, end_row As Long, con_cell As Variant
con_cell = Range("B1")
'end_row = Range("1048576" & Rows.Count).End(xlUp).Rows
For Each wksh In Worksheets
If con_cell = "Yes" Then
Set DB_range = Range("2" & Rows.Count).End(xlDown).Rows
DB_range.Copy
wksh("Main").Activate
'row_end = Range("2" & Rows.Count).End(xlUp).Rows
Range("A1").End(xlDown).Offset(1, 0).Paste
End If
Next wksh
End Sub
There are quite a few issues here - I suggest you do some reading on VBA basics - syntax, objects, methods etc.
I've assumed you are only copying column B.
Sub Migrate_Sheets()
Dim wksh As Worksheet, DB_range As Range
For Each wksh In Worksheets
If wksh.Name <> "Main" Then 'want to exclude this sheet from the check
If wksh.Range("B1").Value = "Yes" Then 'refer to the worksheet in the loop
Set DB_range = wksh.Range("B2", wksh.Range("B" & Rows.Count).End(xlUp)) 'you need Set when assigning object variables
DB_range.Copy Worksheets("Main").Range("A" & Rows.Count).End(xlUp).Offset(1, 0) 'better to work up from the bottom and then go down 1
End If
End If
Next wksh
End Sub
See if this helps, though you might need to make some minor changes to match your data sets..
Sub Migrate_Sheets()
Dim wksh As Worksheet, mainWS As Worksheet
Dim DB_range As Range, con_cell As String
Dim lRow As Long, lCol As Long, lRowMain As Long
Set mainWS = ThisWorkbook.Worksheets("Main")
For Each wksh In Worksheets
con_cell = wksh.Range("B1").Value 'You want to use this variable within the loop
If wksh.Name <> "Main" And con_cell = "Yes" Then
lRowMain = lastRC(mainWS, "row", 1) + 1 'Add 1 to the last value to get first empty row
lRow = lastRC(wksh, "row", 1) 'Get the last row at column 1 - adjust to a different column if no values in column 1
lCol = lastRC(wksh, "col", 2) 'Get the last column at row 2 - adjust to a different row if no values in row 2
With mainWS
.Range(.Cells(lRowMain, 1), .Cells(lRowMain + lRow - 1, lCol)).Value = wksh.Range(wksh.Cells(2, 1), wksh.Cells(lRow, lCol)).Value
End With
End If
Next wksh
End Sub
Function lastRC(sht As Worksheet, RC As String, Optional RCpos As Long = 1) As Long
If RC = "row" Then
lastRC = sht.Cells(sht.Rows.Count, RCpos).End(xlUp).row
ElseIf RC = "col" Then
lastRC = sht.Cells(RCpos, sht.Columns.Count).End(xlToLeft).Column
Else
lastRC = 0
End If
End Function

Resources