Speeding up macro that goes through a workbook overwriting sheets by value - excel

I made an Excel VBA macro that goes through a workbook sheet by sheet and if the sheet contains no pivots it will overwrite it by value. Unfortunately, on at least one workbook it takes so long that I can go through each sheet myself faster. I am wondering what to do to speed it up. Can anyone suggest what I need to do to accomplish this?
' Convert entire workbook's worksheets to values
'
Sub workbook_overrideSheetsToValues_noSave()
Dim answer As Long, c As Long, ws As Worksheet, report As String
answer = MsgBox("Overwrite formulas in this workbook?", vbYesNo + vbQuestion, "Warning! Formula overwrite!")
If answer = vbNo Then Exit Sub
For Each ws In Worksheets
' only copy over by value if there aren't any pivot tables in the sheet.
If ws.PivotTables.count = 0 Then
Call copySheetByValue(ws.Name)
' save all sheets being skipped
Else
c = c + 1
report = report & Chr(10) & c & ". " & ws.Name
End If
Next ws
If report <> "" Then Call MsgBox("Sheets with pivots were skipped:" & report, 0, "Warning!")
End Sub
Sub copySheetByValue(sheetName As Variant, Optional cellPos As String = "A1")
Dim vFlag As Boolean
' Handle case where sheet is hidden
If sheets(sheetName).Visible = False Then
sheets(sheetName).Visible = True
vFlag = True
End If
Worksheets(sheetName).Unprotect
On Error Resume Next
Worksheets(sheetName).ShowAllData ' Clear filters on all columns
Worksheets(sheetName).Cells.EntireColumn.Hidden = False ' Unhide all columns
On Error GoTo 0
Worksheets(sheetName).Cells.Copy
Worksheets(sheetName).Cells.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Application.Goto Worksheets(sheetName).Range(cellPos)
' Hide sheet if it was unhidden above
If vFlag = True Then
sheets(sheetName).Visible = False
vFlag = False
End If
End Sub
The workbook where it works really slowly has 27 worksheets with 12 containing pivots. The 15 remaining each have under 1000 rows with the exception of one containing 24000. Doing a Ctrl-A, Ctrl-C and then pasting by value only takes a moment when done manually.

Ben,
First thing would be to add a few controls to make sure Excel isn't allowed to calculated things:
Application.ScreenUpdating=False
Application.Calculation = xlCalculationManual 'xlCalculationAutomatic to revert back
Application.EnableEvents = False
Application.DisplayAlerts = False
Application.DisplayStatusBar = False
Application.StatusBar = False
Then, you did a great thing using Worksheets(sheetName) to make sure your code really execute on the good worksheet but you should really encapsulate it in a With block to avoid the code to evaluate what this Worksheet object is:
With Worksheets(sheetName)
' Handle case where sheet is hidden
If .Visible = False Then
.Visible = True
vFlag = True
....
' Hide sheet if it was unhidden above
If vFlag = True Then
.Visible = False
vFlag = False
End If
End with
Finally, think about writing the value to your cell instead of doing a copy-paste, because copy-paste is really slow. Think about limiting your macro to the range your worksheet really use.
'Supposing your data start at A1
Dim EndRow As Long
Dim EndColumn As Long
With Worksheets(sheetName)
EndRow = .Range("A" & .Rows.Count).End(xlUp).Row
EndColumn = .Cells(1, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(1, 1), .Cells(EndColumn, EndColumn)).Value2 = .Range(.Cells(1, 1), .Cells(EndColumn, EndColumn)).Value2
End With

Related

Is there any way to fix this loop in VBA Excel?

I have few sheets in my Excel. I want this code to apply Some specific Sheet. Since I am not good at vba I am unable to do it. Please somebody help me. How do I add Sheet3 to 17 to this code so that code only run for these sheets.
Sub insertRowsSheets()
' Disable Excel properties before macro runs
With Application
.Calculation = xlCalculationManual
.EnableEvents = False
.ScreenUpdating = False
End With
' Declare object variables
Dim ws As Worksheet, iCountRows As Integer
Dim activeSheet As Worksheet, activeRow As Long
Dim startSheet As String
' State activeRow
activeRow = ActiveCell.Row
' Save initial active sheet selection
startSheet = ThisWorkbook.activeSheet.Name
' Trigger input message to appear - in terms of how many rows to insert
iCountRows = Application.InputBox(Prompt:="How many rows do you want to insert, starting with row " _
& activeRow & "?", Type:=1)
' Error handling - end the macro if a zero, negative integer or non-integer value is entered
If iCountRows = False Or iCountRows <= 0 Then End
' Loop through the worksheets in active workbook
For Each ws In ActiveWorkbook.Sheets
ws.Activate
Rows(activeRow & ":" & activeRow + iCountRows - 1).Insert
Range("A9").Select
Range("A8:C8").Select
Selection.Copy
Range("A9").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Range("D8:J8").Select
Selection.AutoFill Destination:=Range("D8:J9")
Range("D8:J9").Select
Range("K8:L8").Select
Selection.Copy
Range("K9").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Application.CutCopyMode = False
Range("M8:T8").Select
Selection.AutoFill Destination:=Range("M8:T9")
Range("M8:T9").Select
Range("A8").Select
Next ws
' Move cursor back to intial worksheet
Worksheets(startSheet).Select
Range("A8").Select
' Re-enable Excel properties once macro is complete
With Application
.Calculation = xlCalculationAutomatic
.EnableEvents = True
.ScreenUpdating = True
End With
End Sub
Update Worksheets
This should work the same way as before.
At least it should help you to figure out how to loop through an array of worksheet names instead of the worksheets collection.
I could not figure out the logic of copying and filling. Shouldn't you be filling as many rows as the user selected starting from the active row?
The Code
Option Explicit
Sub insertRowsSheets()
' Define Worksheet Names Array.
Dim wsNames As Variant ' Tab names, not code names.
wsNames = Array("Sheet3", "Sheet4", "Sheet5", "Sheet6", "Sheet7", _
"Sheet8", "Sheet9", "Sheet10", "Sheet11", "Sheet12", _
"Sheet13", "Sheet14", "Sheet15", "Sheet16", "Sheet17")
' Declare object variables
Dim wb As Workbook
Dim ws As Worksheet
Dim RowsCount As Long
Dim ActiveRow As Long
Dim StartSheet As String
Dim i As Long
' Define workbook.
Set wb = ThisWorkbook ' The workbook containing this code.
' State activeRow
ActiveRow = ActiveCell.Row
' Trigger input message to appear - in terms of how many rows to insert
RowsCount = Application.InputBox(Prompt:="How many rows do you want to insert, starting with row " _
& ActiveRow & "?", Type:=1)
' Error handling - end the macro if a zero, negative integer or non-integer value is entered
If RowsCount = False Or RowsCount <= 0 Then Exit Sub
' Loop through the worksheets.
For i = LBound(wsNames) To UBound(wsNames)
With wb.Worksheets(wsNames(i))
.Rows(ActiveRow & ":" & ActiveRow + RowsCount - 1).Insert
.Range("A9:C9").Value = .Range("A8:C8").Value
.Range("D8:J8").AutoFill Destination:=.Range("D8:J9")
.Range("K9:L9").Value = .Range("K8:L8").Value
.Range("M8:T8").AutoFill Destination:=.Range("M8:T9")
End With
Next i
End Sub
' Loop through the worksheets in active workbook
For i = 3 To 17 Step 1 'This runs from the 3rd Sheet to the 17th irrespective of the name. Use array method if the sheets are mixed up
If WorksheetIDExists(i, ActiveWorkbook) Then
Set ws = ActiveWorkbook.Worksheets(i)
With ws
.Rows(activeRow & ":" & activeRow + iCountRows - 1).Insert '<- Kindly note that, if the active row is above A8, the whole script becomes a mess
.Range("A8:C8").Copy
.Range("A9").PasteSpecial Paste:=xlPasteValues
.Range("D8:J9").FillDown
.Range("K8:L8").Copy
.Range("K9").PasteSpecial Paste:=xlPasteValues
.Range("M8:T8").FillDown
.Range("A8").Select
End With
End If
Next i
Add this Function as well.
Function WorksheetIDExists(shtid As Integer, wb As Workbook) As Boolean
Dim sht As Worksheet
On Error Resume Next
Set sht = wb.Worksheets(shtid)
On Error GoTo 0
WorksheetIDExists = Not sht Is Nothing
End Function

Auto Filter a sheet list and delete marked sheets and create new updated sheet from a sample sheet

I am taking a shot at VBA for the first time so hoping someone can help. I have a large model with lots of sheets which are from a template sample worksheet and with value set to the serial number of the sheet on each one and the name of the worksheet set to on the master sheet list.
The master sheet list has three columns
Sheet Number--Sheet Name--Delete Flag
1-- Baby_24-- Yes
2-- Baby_36-- No
3-- Baby_48-- No
4-- Baby_60-- Yes
Trying to write a macro that goes through the master sheet list (Columns A through C), filters for Delete Flag "Yes", deletes all the sheets in the filtered dataset.
After it does that then it should go through the same list and recreate the sheets again by copying the sheet and renaming to in the master list and updating cell value B$2$ on that sheet to the sheet number in the master list. This is what I have so far.
The code generates a debug error and deletes only the first filtered sheet market "Yes" in the set and never goes to the next sheet.
Sub DeleteSheets()
' Delete Sheets Marked as Yes on SkuGroup Worksheet
Dim rRange As Range, filRange As Range, Rng As Range
' Turn off Alerts
Application.DisplayAlerts = False
'Remove any filters
ActiveSheet.AutoFilterMode = False
'~~> Set your range
Set rRange = Sheets("SKU_Groups").Range("A1:C999")
With rRange
'~~> Set your criteria and filter
.AutoFilter Field:=3, Criteria1:="=Yes"
'~~> Filter, offset(to exclude headers)
Set filRange = .Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow
Debug.Print filRange.Address
For Each Rng In filRange
'~~> Your Code
ActiveCell.Value2 = Range("B" & .Offset(1, 0).SpecialCells(xlCellTypeVisible)(1).Row).Value2
Sheets(ActiveCell.Value2).Delete
Next
End With
'Remove any filters
ActiveSheet.AutoFilterMode = False
' Turn on Alerts
Application.DisplayAlerts = True
End Sub
No need to filter . try this :
Sub DeleteSelectedSheets()
Dim masterSheetName
Dim sh As Worksheet
masterSheetName = "master"
Sheets(masterSheetName).Select
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim rowNum
rowNum = 1
Do Until Cells(rowNum, "B").Value = ""
If Cells(rowNum, "C").Value = "Yes" Then
For Each sh In Worksheets
If sh.Name = Cells(rowNum, "B").Value Then
sh.Delete
Rows(rowNum).Delete Shift:=xlUp
rowNum = rowNum - 1
Exit For
End If
Next
End If
rowNum = rowNum + 1
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

Excel VBA macro works randomly

i need some advice regarding this macro.
This macro cuts and copies from "LATURAP" sheet, rows if specific conditions are met. exmpl. starts with number 170889 and so on.
Problem is that, when i run this macro, it will only works once when i have imported this to excel.
Can somebody explain what i'm missing here?
Sub Laturap()
Dim i As Integer
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
Application.DisplayStatusBar = False
Application.EnableEvents = False
a = Worksheets("LATURAP").Cells(Rows.Count, "A").End(xlUp).Row
For i = 3 To a
'selection from LATURAP to 1708
If Left(Range("A" & i), 6) = 170889
Then
Worksheets("LATURAP").Range("A:J").Rows(i).Cut
Worksheets("1708").Activate
b = Worksheets("1708").Cells(Rows.Count, "A").End(xlUp).Row
Worksheets("1708").Cells(b + 1, 1).Select
Worksheets("1708").Paste
Worksheets("LATURAP").Activate
.........
You could try this(comments added in code)...
Sub Laturap()
Dim ws1 As Worksheet, ws2 As Worksheet, i As Long
Set ws1 = ThisWorkbook.Sheets("LATURAP")
Set ws2 = ThisWorkbook.Sheets("1708")
x = 1
With ws1 'wrap your code in the worksheet variable
For i = 3 To .Cells(.Rows.Count, 1).End(xlUp).Row 'you can assign the last row as a variable and use it, this cuts down the lines of code
If Left(.Range("A" & i), 6) = 170889 Then 'check the first 6 characters in each cell in Col A for the value
With .Range("A" & i).Resize(, 10) 'if a match select the range in the row from Col A to Col J using resize.
.Copy Destination:=ws2.Cells(Rows.Count, 1).End(xlUp).Offset(x, 1) 'copy the range pan paste to the first cell in ColB in ws2
.Clear 'clear the range in ws1
x = x + 1 'increases 1 to paste to the next empty row, must be within the If statement
End With
End If
Next i
End With
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Application.DisplayStatusBar = True
Application.EnableEvents = True
End Sub

copy every cells in a column to particular cell in new sheet every time with a loop

I seek your help to copy the cell values in (column D) of the first worksheet to a specified cell location in 16 existing worksheets
i want value in
D2 in in sheet1 to sheet2 (G5)
D3 in in sheet1 to sheet3 (G5)
D4 in in sheet1 to sheet4 (G5)
and so on until the D16 is copied to G5 of sheet16
i am a newbie, i looked into several answers and tried to work out on my own but.... nothing happened
Sub latitude()
Dim WS_Count As Integer
Dim I As Integer
WS_Count = ActiveWorkbook.Worksheets.Count
For I = 1 To WS_Count
Do Until IsEmpty(ActiveCell)
Sheets("Calculations").Select
Range("d2").Copy
ActiveCell.Offset(1, 0).Select
'at this point i want it to copy "D3" on next loop
ActiveSheet.Range("G5").PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Loop
ActiveSheet.Next.Select
' and because the "Sheets("Calculations").Select" above takes it to the first sheet the whole script is a waste till now
Next I
End Sub
Alistairs attempt is good, i would however not use shtname = "Sheet" & i, instead try the following solution and think about bulletprooving it a bit (existance of worksheets) ;)
Sub Copy_to_G5()
Dim i As Integer
With Application
.DisplayAlerts = False
.ScreenUpdating = False
End With
i = 2
Do Until i = 17
With ThisWorkbook
.Worksheets(1).Cells(i, 4).Copy
.Worksheets(i).Range("G5").PasteSpecial
End With
i = i + 1
Loop
With Application
.DisplayAlerts = True
.ScreenUpdating = True
End With
End Sub
Give this a try.
Option Explicit
Sub Copy_to_G5()
Dim sht1 As Worksheet, ws As Worksheet
Dim i As Integer
Dim shtname As String
With Application
.DisplayAlerts = False
.ScreenUpdating = False
End With
Set sht1 = Sheets("Sheet1")
i = 2
Do Until i = 17
shtname = "Sheet" & i
sht1.Cells(i, 4).Copy
Sheets(shtname).Range("G5").PasteSpecial
i = i + 1
Loop
With Application
.DisplayAlerts = True
.ScreenUpdating = True
End With
End Sub

Excel 2007, Copying rows from one sheet to another based on a value in 1 column

I'm trying to copy a range of rows where the rows chosen are based on the value in one cell.I want to do this for all rows containing the same value in a cell, then move on to the next value an append to the bottom of the first list.
Below is my attempt at explaining what I wish to achieve - hopefully the above will help explain more my dilemma. I have looked around for this but not quite found what I want. I thought it would be simple and probably is.
I receive a data dump with thousands of rows of data and 18 columns. Based on the value of column P "Contract" I want to copy entire rows into a new single worksheet workingdata. Not all the data will go into the workingdata worksheet.
The contract numbers are c1234, c1235, c2345 etc.
What i am after achieving is copying and sorting, so copy all the rows of data where contract number is c1234, in workingdata, then directly below it copy all rows where contract is c1235 and so on.
I thought I could select the range P:P and sort but to no avail.
Sheets("Data Dump").Select
Columns("P:P").Select
If Selection.Value = "C1234" Then
Selection.EntireRow.copy
I know I should post what i have tried, but it would be a pathetic, for some reason I just can't seem to get my head round this one.
Here's my latest effort - I know there are errors
Dim oWorksheet As Excel.Worksheet
Dim oRangeSource As Excel.Range
Dim oRangeDest As Excel.Range
Set oWorksheet = Worksheets("DataDump")
Set oRangeSource = oWorksheet.Range("p:p")
Set oRangeDest = Worksheets("workingdata")
If oRangeSource="CA0004000" Then Select.EntireRow
Selection.EntireRow.copy
Sheets("workingdata").Select.Paste
End If
latest effort but does not sort data or get rid of unwanted, I have to do a manual filter and sort which sorts of defeats the object of the macro
Sub copy()
'
' copy Macro
'
Dim rngContracts As Range: Set rngContracts = Sheets("DataDump").Range("P:P")
Dim wsData As Worksheet
Dim wsFound As Boolean: wsFound = False
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name = "Working Data" Then
Set wsData = ws
wsFound = True
Exit For
End If
Next ws
If wsFound = False Then
Application.CutCopyMode = False
ActiveSheet.Range("A1").EntireRow.copy
Set wsData = Sheets.Add(After:=Sheets(Sheets.Count))
wsData.Name = "Working Data"
wsData.Range("A1").EntireRow.PasteSpecial xlPasteAll, Transpose:=False
End If
Dim iCell As Range
For Each iCell In rngContracts
If iCell.EntireRow.Hidden = False Then
Application.CutCopyMode = False
iCell.EntireRow.copy
wsData.Range("P" & Rows.Count).End(xlUp).Offset(1, 0).EntireRow.PasteSpecial xlPasteAll, Transpose:=False
End If
Next iCell
Application.CutCopyMode = False
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Latest attaempt - copies the data I need but does not sort:
Sub copytest()
'
' copytest Macro
'
Set MR = Sheets("data Dump").Range("P:P")
For Each cell In MR
If cell.Value = "CA000154" Then
cell.EntireRow.copy
Sheets("working data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
End If
If cell.Value = "CA000220" Then
cell.EntireRow.copy
Sheets("working data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
End If
If cell.Value = "CA000393" Then
cell.EntireRow.copy
Sheets("working data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
End If
If cell.Value = "CA000429" Then
cell.EntireRow.copy
Sheets("working data").Range("A" & Rows.Count).End(xlUp).Offset(1, 0).PasteSpecial
End If
Application.CutCopyMode = False
Next
End Sub
Record a macro to set filters on your data select one filter only.
Then, edit the code and loop through each filter copying the visible range on to your sheet. This must also sort your data as the filters are already sorted.
Also, take a look at creating filter arrays in the Excel VBA help with regards to using them to sort.

Resources