Ignore empty cells in for each VBA - vba

I am having a problem with my loop(i go throu columns in every worksheet and copy them common column ) in VBA. And I wan't to ignore empty cells... any ideas? Bellow is my code
Application.ScreenUpdating = False
lastRowMaster = 1
For Each Ws In Sheets(Array("1L", "5L"))
lastRow = Ws.Range("A" & Rows.Count).End(xlUp).row
Ws.Range("A1:A" & lastRow).Copy Destination:=Worksheets("Podatki plana").Range("A" & lastRowMaster)
lastRowMaster = Worksheets("Podatki plana").Range("A" & Rows.Count).End(xlUp).row + 1
Next
Application.ScreenUpdating = True
MsgBox "Done!"

I altered this line of code:
Ws.Range("A1:A" & lastRow).Copy Destination:=Worksheets("Podatki plana").Range("A" & lastRowMaster)
To this:
Ws.Range("A1:A" & lastRow).SpecialCells(xlCellTypeConstants).Copy Destination:=Worksheets("Podatki plana").Range("A" & lastRowMaster)
Using the .SpecialCells(xlCellTypeConstants) qualifier selects only cells that have a value in them. You could change xlCellTypeConstants to xlCellTypeFormulas or any of the options listed on this MSDN article.
The benefit with this is that you don't have to loop through each cell, which is a perfectly good solution but comes with a performance penalty.
Tested in Excel 2013.

Maybe just set each of the destination cells to the origin cell when the cell is not empty, like so
Application.ScreenUpdating = False
lastRowMaster = 1
lastRow = Ws.Range("A" & Rows.Count).End(xlUp).row
nextRow = 1
For Each Ws In Sheets(Array("1L", "5L"))
for i = 1 to lastRow
if Not IsEmpty(Ws.Cells(i, 1)) then
Worksheets("Podatkiplana").cells(nextRow, 1) = Ws.cells(i,1)
nextRow = nextRow + 1
end if
next i
Next
Application.ScreenUpdating = True
MsgBox "Done!"

Application.ScreenUpdating = False
lastRowMaster = 1
For Each Ws In Sheets(Array("1L", "5L"))
lastRow = Ws.Range("A" & Rows.Count).End(xlUp).row
For i = 1 to lastrow
lastRowMaster = Worksheets("Podatki plana").Range("A" & rows.Count).End(xlUp).row + 1
If ws.cells(i, 1)<> "" Then Worksheets("Podatki plana").Cells(lastRowMaster, 1) = ws.cells(i,1)
next i
Next
Application.ScreenUpdating = True
MsgBox "Done!"

Related

VBA - Hide rows macro limit

I have the code below to hide all blank cells on my sheet. How do I set the hide range to 100 so after cell 100 if the remaining ones are blank it doesn't hide them. Only cells within the 1-100 limit get hidden if blank.
Sub HideRow()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Projects Dashboard")
Dim LRowC, LRowD, LRowF, LRowH, LRow As Long
LRowC = ws.Range("C" & ws.Rows.Count).End(xlUp).Row
LRowD = ws.Range("D" & ws.Rows.Count).End(xlUp).Row
LRowF = ws.Range("F" & ws.Rows.Count).End(xlUp).Row
LRowH = ws.Range("H" & ws.Rows.Count).End(xlUp).Row
LRow = Application.WorksheetFunction.Max(LRowC, LRowD, LRowF, LRowH)
Dim I As Long
Application.ScreenUpdating = False
ws.Rows.Hidden = False
For I = LRow To 7 Step -1
If ws.Range("C" & I).Text = "" And ws.Range("D" & I).Text = "" And ws.Range("F" & I).Text = "" And ws.Range("I" & I).Text = "" Then
ws.Rows(I).EntireRow.Hidden = True
End If
Next I
Application.ScreenUpdating = True
End Sub
If I understand your question and code, it seems that you would want limit your LRow value to be a max of 100.
Should be as simple as adding one line of code:
...
LRow = Application.WorksheetFunction.Max(LRowC, LRowD, LRowF, LRowH)
If LRow > 100 Then LRow = 100
Dim I As Long
...

deleting rows with blank cells and criteria VBA

I have columns from A - S, where I need to delete the headers and blank cells, my criteria for lookup in deleting headers are "Transaction" & "Source" but it seems it's skipping rows. I have a total of 79,000 rows but code only goes till 39,000. I've tried everything I can find over. still nothing happens.
I'm also starting the formatting and deleting on row 209 up to lastrow.
Option Explicit
Sub Project_M()
Dim lastrow As Long
Dim cc As Long
Dim dd As Long
lastrow = WorksheetFunction.CountA(Columns(1))
Application.ScreenUpdating = False
Call ClearFormats
lastrow = WorksheetFunction.CountA(Columns(1))
Columns(1).Insert shift:=xlToRight
Range("A209:A" & lastrow).Formula = "=ROW()" 'inserting dummy rows
Range("A209:A" & lastrow).Value = Range("A210:A" & lastrow).Value
Range("U209:U" & lastrow).Formula = "=IF(AND(ISERROR(SEARCH(""Transaction"",B209)),ISERROR(SEARCH(""Source"", B209))),1,0)"
Range("U209:U" & lastrow).Value = Range("U209:U" & lastrow).Value
''''' delete headers : only working till row 39,0000
Range("A209:U" & lastrow).Sort Key1:=Range("U209"), Order1:=xlAscending
cc = WorksheetFunction.CountIf(Columns(21), "0")
If cc <> 0 Then
Range("A209:U" & cc).Select
Range("A209:U" & cc).EntireRow.Delete
lastrow = lastrow - cc
End If
Range("A209:U" & lastrow).Sort Key1:=Range("A209"), Order1:=xlAscending
Range("U:U").ClearContents
Range("A:A").Delete
ActiveSheet.UsedRange.Columns.AutoFit
End Sub
Sub deleteBlank() 'not working
Dim lastrow As Integer
lastrow = Range("A" & rows.Count).End(xlUp).Row
Range("B2:B" & lastrow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
Sub ClearFormats() ' working
Dim rng As Range
Dim lastrow As Long
Dim ws As Worksheet
lastrow = Range("A" & rows.Count).End(xlUp).Row
Application.ScreenUpdating = False
On Error Resume Next
Set rng = Range("A209:S" & lastrow).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rng Is Nothing Then
rng.ClearFormats
End If
On Error Resume Next 'not working in deleting blank cells
ws.Columns("A209:S" & lastrow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
End Sub
Sub DeleteExtra() ' not working
Dim Last As Long
Dim i As Long
Last = Cells(rows.Count, "A").End(xlUp).Row
For i = Last To 1 Step 1
If (Cells(i, "A209").Value) = "Transaction" And (Cells(i, "A209").Value) = "Source" And (Cells(i, "A209").Value) = "" And (Cells(i, "A209").Value) = " " Then
Cells(i, "A").EntireRow.Delete
End If
Next i
End Sub
Sub deleteBlankcells() '''not working
Dim lastrow As Long
Dim cc As Long
lastrow = WorksheetFunction.CountA(Columns(1))
Range("A209:A" & lastrow).Formula = "=ROW()" 'inserting dummy rows
Range("A209:A" & lastrow).Value = Range("A210:A" & lastrow).Value
Range("U209:U" & lastrow).Formula = "=IF(AND(ISBLANK(A209),ISBLANK(A209)),0,1)"
Range("U209:U" & lastrow).Value = Range("U209:U" & lastrow).Value
Range("A209:U" & lastrow).Sort Key1:=Range("U209"), Order1:=xlAscending
cc = WorksheetFunction.CountIf(Columns(21), "0")
If cc <> 0 Then
Range("A209:U" & cc).Select
Range("A209:U" & cc).EntireRow.Delete
lastrow = lastrow - cc
End If
Range("A209:U" & lastrow).Sort Key1:=Range("A209"), Order1:=xlAscending
Range("U:U").ClearContents
Range("A:A").Delete
End Sub
I've tried different attempts but not working. codes are commented.
Thanks!
With the help and ideas of users, I've come to this simple code and got it working.
Credits to all of them! Cheers!
Option Explicit
Sub Project_M()
Dim Last As Long
Dim i As Long
Application.ScreenUpdating = False
Last = cells(rows.Count, "A").End(xlUp).Row
Range("A209:S" & Last).UnMerge
Range("A209:S" & Last).WrapText = False
For i = Last To 209 Step -1
If (cells(i, "A").Value) = "Source" Or (cells(i, "A").Value) = 0 Or (cells(i, "A").Value) = "End of Report" Or (cells(i, "A").Value) = "Transaction" Then
cells(i, "A").EntireRow.Delete
End If
Next i
ActiveSheet.UsedRange.Columns.AutoFit
Application.ScreenUpdating = True
End Sub
Starting from the last row of the column for i = Last up to the row I want to start my formatting and deleting To 209 and Step -1 to move up.

copy lastrow of masterfile to multiple created worksheets then perform a Subtotal formula in a column lastrow

I have a master file which is (JV501) where I filter through column AB (currency) then copy those to createdsheets, my problem now is the lastrow from master file which I need to include to every created worksheets since it starts in column R and from there under column AD (which is all null) lastrow is where I shall perform a subtotal of AC2 up to lastrow so the subtotal shall inline with the lastrow copied.
Option Explicit
Sub SortCurrency()
Dim currRng As Range, dataRng As Range, currCell As Range
Dim LastCol As Long, lastRow As Long, lastrow2 As Long, TheLastRow As Long
Call DeleteSheets
With Worksheets("JV501")
Set currRng = .Range("AB1", .Cells(.Rows.Count, "AB").End(xlUp))
Set dataRng = Intersect(.UsedRange, currRng.EntireRow)
LastCol = Range("A1").End(xlToRight).Column
TheLastRow = Range("A1").End(xlDown).Row
lastRow = Range("AB2").End(xlDown).Row
Range("AB2:AB" & lastRow).sort key1:=Range("AB2" & lastRow), _
order1:=xlAscending, Header:=xlNo
Range("AF:XFD").EntireColumn.Delete
With .UsedRange
With .Resize(1, 1).Offset(, .Columns.Count)
With .Resize(currRng.Rows.Count)
.Value = currRng.Value
.RemoveDuplicates Array(1), Header:=xlYes
For Each currCell In .SpecialCells(xlCellTypeConstants)
currRng.AutoFilter field:=1, Criteria1:=currCell.Value
If Application.WorksheetFunction.Subtotal(103, currRng) - 1 > 0 Then
dataRng.SpecialCells(xlCellTypeVisible).Copy Destination:=GetOrCreateWorksheet(currCell.Value).Range("A1")
Range("J:Q").EntireColumn.Delete
Range("A:A").EntireColumn.Delete
Columns("A:AE").Select
Selection.EntireColumn.AutoFit
End If
Next currCell
.ClearContents
End With
End With
End With
.AutoFilterMode = False
End With
Call checklist
End Sub
Function GetOrCreateWorksheet(shtName As String) As Worksheet
On Error Resume Next
Set GetOrCreateWorksheet = Worksheets(shtName)
If GetOrCreateWorksheet Is Nothing Then
Set GetOrCreateWorksheet = Worksheets.Add(After:=Sheets(Sheets.Count))
GetOrCreateWorksheet.Name = shtName
End If
End Function
this is my code so far. I'm confused if how I shall do this.
Every help is appreciated!
In trying to compute for a a column range i've come up and got it working by adding this in my loop in creating sheets.
'subtotal of debit
lastrowSrc = Range("AC" & Rows.Count).End(xlUp).Row + 1
Range("AC" & lastrowSrc & ":AC" & lastrowSrc).Formula = "=SUBTOTAL(9,AC2:AC" & lastrowSrc - 1 & ")"
'copy ac to ad
Range("AC" & lastrowSrc & ":AC" & lastrowSrc).Cut Destination:=Range("AC" & lastrowSrc).Offset(0, 1)
in column AC is where I will compute the subtotal of debit then copy it to another column which is AD which is null I've pasted it by column AC then offset
For copying the columns not included in criteria of extracting I've done it one by one
dim internalS as long, 'and so on
internalR = Range("R" & Rows.Count).End(xlUp).Row + 1
copyR.Copy Destination:=Range("R" & internalR)
internalS = Range("S" & Rows.Count).End(xlUp).Row + 1
copyS.Copy Destination:=Range("S" & internalS)
internalT = Range("T" & Rows.Count).End(xlUp).Row + 1
copyT.Copy Destination:=Range("T" & internalT)
internalU = Range("U" & Rows.Count).End(xlUp).Row + 1
copyU.Copy Destination:=Range("U" & internalU)
internalV = Range("V" & Rows.Count).End(xlUp).Row + 1
copyV.Copy Destination:=Range("V" & internalV)
internalW = Range("W" & Rows.Count).End(xlUp).Row + 1
copyW.Copy Destination:=Range("W" & internalW)
internalX = Range("X" & Rows.Count).End(xlUp).Row + 1
copyX.Copy Destination:=Range("X" & internalX)
internalY = Range("Y" & Rows.Count).End(xlUp).Row + 1
copyY.Copy Destination:=Range("Y" & internalY)
internalZ = Range("Z" & Rows.Count).End(xlUp).Row + 1
copyZ.Copy Destination:=Range("Z" & internalZ)
internalAE = Range("AE" & Rows.Count).End(xlUp).Row + 1
copyAE.Copy Destination:=Range("AE" & internalAE)
also inserted this in my loop in creating new worksheets

VBA Excel AutoFilter Error

I am getting following error when trying to auto filter in vba:
The object invoked has disconnected from its clients.
So what i am trying to do is auto filter, search for empty spaces and delete the rows. Can anyone please help?
I have tried the standard solutions provided online e.g. option explicit etc but to no avail.
Data:
Code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim lngLastRow As Long
Dim lngLastRowD As Long
Application.ScreenUpdating = False
'Concatenate the Row A and B
lngLastRow = Cells(Rows.Count, "A").End(xlUp).Row
Worksheets(1).Range("D2:D" & lngLastRow).Value = Evaluate("=A2:A" & lngLastRow & "&""""&" & "B2:B" & lngLastRow)
lngLastRowD = Worksheets(1).Cells(Rows.Count, "D").End(xlUp).Row
Set ws = Worksheets(1)
Set Rng = Worksheets(1).Range("A2:A" & lngLastRowD)
With Rng
.AutoFilter field:=1, Criteria1:=""
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
ws.AutoFilterMode = False
Application.ScreenUpdating = True
ThisWorkbook.Sheets(1).Range("A2").Select
End Sub
Since Worksheets() want the name of the sheet, like "Sheet1", use sheets(1).
Why are you creating the variable ws and rng when you only use them once
I ran this and it deleted rows with no data in column A.
Private Sub Worksheet_Change()
Dim lngLastRow As Long
Dim lngLastRowD As Long
Application.ScreenUpdating = False
'Concatenate the Row A and B
lngLastRow = Cells(Rows.Count, "A").End(xlUp).Row
sheets(1).Range("D2:D" & lngLastRow).Value = Evaluate("=A2:A" & lngLastRow & "&""""&" & "B2:B" & lngLastRow)
lngLastRowD = Worksheets(1).Cells(Rows.Count, "D").End(xlUp).Row
With sheets(1).Range("A2:A" & lngLastRowD)
.AutoFilter field:=1, Criteria1:=""
.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
sheets(1).AutoFilterMode = False
Application.ScreenUpdating = True
Sheets(1).Range("A2").Select
End Sub
In the end i restored in approaching the issue from another angle:
Dim i As Integer, counter As Integer
i = 2
For counter = 1 To lngLastRowD
If Worksheets(1).Range("A2:A" & lngLastRowD).Cells(i) = "" And Worksheets(1).Range("D2:D" & lngLastRowD).Cells(i) <> "" Then
Worksheets(1).Range("A2:A" & lngLastRowD).Range("A" & i & ":D" & lngLastRowD).Select
Selection.Delete
GoTo TheEND
Else
i = i + 1
Debug.Print "i is " & i
End If
Next

Suggestions on how to speed up loop

I have the following code. I was wondering if there is an easy way to rewrite it so that it takes less time to run? Currently, I have about 13,000 rows to loop through and it takes approximate 3-5 minutes to run. Thanks!
Sheets("wkly").Activate
Dim i As Long
Lastrow = Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To Lastrow
If Range("S" & i) > 0.005 Then
Range("Z" & i, "AA" & i).Copy
Range("AC" & i, "AD" & i).PasteSpecial xlPasteValues
End If
Application.ScreenUpdating = False
Next i
I believe this will help make it a lot faster. No looping and no copy and paste needed.
Application.ScreenUpdating = False
Application.Calculation = xlManual
Dim wks As Worksheet, Lastrow As Long
Set wks = Sheets("wkly")
With wks
Lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
.Range("S1:S" & Lastrow).AutoFilter 1, ">.005"
'Assumes you will always have values greater than .005, if not you need to error trap
Dim rngFilter As Range
Set rngFilter = .Range("S2:S" & Lastrow).SpecialCells(xlCellTypeVisible) 'assumes row 1 is header row
rngFilter.Offset(, 10).Value = rngFilter.Offset(, 7).Value
rngFilter.Offset(, 11).Value = rngFilter.Offset(, 8).Value
End With
Application.ScreenUpdating = True
UPDATE
I know you accepted the answer already, but in case you want to know how to do this by using an array to loop through, here it is below:
Dim wks As Worksheet, varStore As Variant, Lastrow As Long, i As Long
Application.ScreenUpdating = False
Application.Calculation = xlManual
Set wks = Sheets("wkly")
With wks
Lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
varStore = .Range("S2:S" & Lastrow)
For i = LBound(varStore, 1) To UBound(varStore, 1)
If varStore(i, 1) > 0.005 Then .Range("AC" & i + 2 & ":AD" & i + 2).Value = .Range("Z" & i + 2 & ":AA" & i + 2).Value
Next
End With
Application.ScreenUpdating = False
If you do operations on a large number of cells, copying them into an array and writing them back after the processing is usually the fastest. The following code runs in 0.04s on my machine (based on Scott's answer, but using arrays also for the writing):
Dim wks As Worksheet
Dim varCompare As Variant, varSource As Variant, varTarget As Variant
Dim Lastrow As Long, i As Long
Application.ScreenUpdating = False
Application.Calculation = xlManual
Set wks = Sheets("wkly")
With wks
Lastrow = .Range("A" & .Rows.Count).End(xlUp).Row
varCompare = .Range("S2:S" & Lastrow)
varSource = .Range("Z2:AD" & Lastrow)
varTarget = .Range("AC2:AD" & Lastrow)
For i = LBound(varCompare, 1) To UBound(varCompare, 1)
If varCompare(i, 1) > 0.005 Then
varTarget(i, 1) = varSource(i, 1)
varTarget(i, 2) = varSource(i, 2)
End If
Next
.Range("AC2:AD" & Lastrow).Value = varTarget
End With
Application.ScreenUpdating = False
Given all the good tips, and include the following too. Please give a try and see how much performance boost you could achieve.
Application.Calculation = xlCalculationManual
lastrow = Range("S" & Rows.Count).End(xlUp).Rows
For i = 1 To lastrow
If Range("S1").Offset(i) > 0.005 Then
Range("AC").Offset(i).Resize(1, 2).Value = Range("Z").Offset(i).Resize(1, 2).Value
End If
Next i