Macro needs cleaned up - excel

I have a workbook I have been working on. This workbook has 3 sheets of information that help populate a MASTER sheet through excel index and match functions as well as other functions. The A2 cell on the MASTER sheet is a drop down box of names. As each name is chosen a macro linked to a button helps summarize the information and then an other button copies and paste the sheet to a new sheet in the workbook. My question is on the macro that summarizes the information. Being new to macros, I put this together with information gathered on the Internet. I noticed that it is hiding some rows when used which is not good and works really slow. Also, not of great important, it places the paste anywhere within the range. Even sometimes lines apart, like on E14 and E16 instead of E14 and E15. I am sure there is a better way of writing this macro and any help and education would be greatly appreciated.
Sub UniqueValues()
Dim ws As Worksheet
'list states for install & service
Application.ScreenUpdating = False
Set ws = Sheets("MASTER")
ws.Range("D94:D144").AdvancedFilter Action:=x1FilterInPlace, Unique:=True
Range("D94:D144").Copy
ws.Range("E14:E19").PasteSpecial x1Values
Application.CutCopyMode = False
Application.ScreenUpdating = True
'list states for overrides
Application.ScreenUpdating = False
Set ws = Sheets("MASTER")
ws.Range("D147:D246")AdvancedFilter Action:=x1FilterInPlace, Unique:=True
Range("D147:D246").Copy
ws.Range("E21:E26").PasteSpecial x1Values
Application.CutCopyMode = False
Application.ScreenUpdating = True
'lists states for licenses
Application.ScreenUpdating = False
Set ws = Sheets("MASTER")
ws.Range("D249:D298").AdvancedFilter Action:=x1FilterInPlace, Unique:=True
Range("D249:D298").Copy
ws.Range("E35:E38").PasteSpecial x1Values
Application.CutCopyMode = False
Application.ScreenUpdating = True
'lists states for commissions
Application.ScreenUpdating = False
Set ws = Sheets("MASTER")
ws.Range("D301:D327").AdvancedFilter Action:=x1FilterInPlace, Unique:=True
Range("D301:D327").Copy
ws.Range("E28:E33").PasteSpecial x1Values
Application.CutCopyMode = False
Application.ScreenUpdating = True
End Sub

The 'In Place' filter + copy paste will be very slow. If you want to improve your code you could use a Dictionary (available in the Microsoft Scripting Runtime)
Sub getUniquesValues(output As Range, cells As Range)
Dim cell As Range
Dim knownValues As New Dictionary
For Each cell In cells
If Not knownValues.Exists(cell.Value) Then
output = cell.Value
Set output = output.Offset(1, 0)
knownValues.Add cell.Value, 1
End If
Next
End Sub
Then all you have to do is call the sub this way :
Sub ImprovedUniqueValues()
Dim cell As Range, output As Range
Dim ws As Worksheet
Set ws = Sheets("MASTER")
Set output = ws.Range("E19")
getUniquesValues output, ws.Range("D94", ws.Range("D94").End(xlDown))
....
End Sub

Related

Unwanted worksheet duplication VBA

I built a code into a command button that identified a single sheet, copies the values and the formulas, and creates a separate detached workbook that we use for ordering material. The original formula worked great and was simple when there was only 1 target sheet. I have added 4 additional sheets to be captured, the core of the formula still works and it copies/detaches a separate workbook for ordering, but now it is also creating a copy of the original workbook as well for no reason.
How can I get it to only copy and detach the sheets in the formula and not the entire workbook?
Private Sub CommandButton1_Click()
' Plain_Copy Macro '
Sheets("PROCUREMENT").Visible = True
Sheets("Request").Visible = True
Sheets("LISTS").Visible = True
Sheets("Copy").Visible = True
Dim TheActiveWindow As Window
Dim TempWindow As Window
Dim ws As Worksheet
With ActiveWorkbook
Set TheActiveWindow = ActiveWindow
Set TempWindow = .NewWindow
.Sheets(Array("REQUESTOR", "PROCUREMENT", "Request", "LISTS", "Copy")).Copy
Application.ScreenUpdating = False
For Each ws In ActiveWorkbook.Worksheets
With ws.UsedRange
.Copy
.PasteSpecial xlPasteFormulasAndNumberFormats
End With
TempWindow.Close
Next ws
Application.CutCopyMode = False
Application.ScreenUpdating = True
End With

Macro to remove all orders with 'XXX' status, then remove all order types besides: Z , L, ZR

We have a monthly process of manually exporting information from SAP to Excel and then creating a production schedule from it. One of the first steps when getting the information to excel is filtering down to certain criteria and removing the rest. I am a begginer with VBA/Macros, and I can only find examples online on how to delete rows via certain criteria instead of deleting rows outside of my desired criteria..
I want to remove all orders with 'XXX' status.
Then I want to remove all order types EXCEPT: Z, L, ZR
I am assuming this is possible, and that I just am not educated enough on vba to figure it out quite yet.. Let me know, thanks!
Apply the filter for the ones you want to keep and copy them to a new workbook or a temporary sheet that you can copy back from.
Option Explicit
Sub Macro1()
Const COL_STATUS = 1 ' column no
Const COL_ORDERTYPE = 4 ' column no
Dim ws As Worksheet, wsTemp As Worksheet
Dim rng As Range
With ThisWorkbook
Set ws = .Sheets("Sheet1")
Set wsTemp = .Sheets.Add(after:=.Sheets(.Sheets.Count))
End With
Application.ScreenUpdating = False
With ws.UsedRange
.AutoFilter COL_STATUS, Array("Z", "L", "ZR"), xlFilterValues
.AutoFilter COL_ORDERTYPE, "<>ZZZ"
.Copy wsTemp.Range("A1")
.AutoFilter
.Cells.Clear
End With
With wsTemp
.UsedRange.Copy ws.Range("A1")
Application.DisplayAlerts = False
.Delete
Application.DisplayAlerts = True
End With
Application.ScreenUpdating = True
MsgBox "Done"
End Sub

Copy filtered fields from one sheet to another without activating

I have a workbook with two sheets.
First is called "Forma"
Second is called "Prices"
I go to Forma, with some VBA shapes I choose a product category. I tag this category name in A1 cell of sheet Prices and then filter products according to this category and then copy filtered ones in Forma again.
Because of activating and deactivating sheets the procedure is working but it is blinking screens between activations. Any better way?
That is a part of my code:
With ActiveSheet
range("j7: m30").ClearContents
End With
'Tag the category in Prices Table
ThisWorkbook.Sheets("Prices").Cells(1, 1).Value = "CategoryName.ex.Computers"
'Filtering and selecting products comparing A1 with Column 3 Categories
Worksheets("Prices").Activate
range("A1:K300").Select
Selection.AutoFilter
Selection.AutoFilter Field:=3, Criteria1:=range("a1").Value
'Copy filtered in Forma Sheet
Dim DbExtract, DuplicateRecords As Worksheet
Set DbExtract = ThisWorkbook.Sheets("Prices")
Set DuplicateRecords = ThisWorkbook.Sheets("Forma")
DbExtract.range("D3:f5000").SpecialCells(xlCellTypeVisible).Copy
DuplicateRecords.Cells(7, 10).PasteSpecial
Copy Filtered Range
Not activating and not selecting will increase performance.
Turning off Application.ScreenUpdating will stop the screen from 'blinking'.
Using variables will increase readability.
Something like the following code could put you on the right track.
The Code
Option Explicit
Sub copyCategory()
Const Criteria As String = "CategoryName.ex.Computers"
Dim wb As Workbook
Set wb = ThisWorkbook
Dim src As Worksheet
Set src = wb.Worksheets("Prices")
Application.ScreenUpdating = False
If src.AutoFilterMode Then
src.AutoFilterMode = False
End If
src.Range("A1").Value = Criteria
src.Range("A1:K300").AutoFilter Field:=3, _
Criteria1:=Criteria
Dim dst As Worksheet
Set dst = wb.Worksheets("Forma")
dst.Range("J7: M30").ClearContents
src.Range("D3:F300").SpecialCells(xlCellTypeVisible).Copy dst.Range("J7")
' If you need some special pasting then rather use the following 3 lines.
'src.Range("D3:F300").SpecialCells(xlCellTypeVisible).Copy
'dst.Range("J7").PasteSpecial
'Application.CutCopyMode = False
Application.ScreenUpdating = True
MsgBox "Data copied.", vbInformation, "Success"
End Sub

VBA won't copy the next table, but keeps pasting the first instead

I have the following code
Sub Workbook_Open()
Dim x As Workbook
Dim y As Workbook
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.DisplayAlerts = False
Application.AlertBeforeOverwriting = False
Set x = ThisWorkbook
Set y = Workbooks.Open("N:\\REAL PATH")
'Opens Data and Pastes Values
x.Worksheets("Event Data").Range("Table1[#All]").Copy
y.Worksheets("CoreData").Range("A1").PasteSpecial Paste:=xlPasteValues
x.Worksheets("Comments").Range("Table2[#All]").Copy
y.Worksheets("CommentsData").Range("A1").PasteSpecial Paste:=xlPasteValues
x.Worksheets("Match Data").Range("Table3[#All]").Copy
y.Worksheets("MatchDetails").Range("A1").PasteSpecial Paste:=xlPasteValues
y.Close SaveChanges:=True
ActiveWorkbook.Save
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
After running the code, I go to the workbook named y, and I find that Table 1's data has been pasted three times. So, basically, the y.Worksheets lines are working properly but it won't copy data from Table 2 or 3. If I hit ctrl + g and type in "Table2[#All]" I am taken to the full Table 2, so I know that the range exists and that VBA should be able to find it. Table 1 contains quite a bit of data (131k rows + columns to DZ), but I don't know if that's relevant.
I find that creating and using intermediate variables greatly helps to clear up any problems in transferring data. Plus, you can look at these variables when debugging to verify they are correctly set.
Try something along these lines:
Option Explicit
Sub Example()
Dim srcWB As Workbook
Dim dstWB As Workbook
Set srcWB = ThisWorkbook
Set dstWB = Workbooks.Open("N:\\REAL PATH")
Dim srcData As Range
Dim dstData As Range
Set srcData = srcWB.Sheets("Event Data").Range("Table1[#All]")
Set dstData = dstWB.Sheets("CoreData").Range("A1").Resize(srcData.Rows.Count, _
srcData.Columns.Count)
dstData.Value = srcData.Value
Set srcData = srcWB.Sheets("Comments").Range("Table2[#All]")
Set dstData = dstWB.Sheets("CommentsData").Range("A1").Resize(srcData.Rows.Count, _
srcData.Columns.Count)
dstData.Value = srcData.Value
Set srcData = srcWB.Sheets("Match Data").Range("Table3[#All]")
Set dstData = dstWB.Sheets("MatchDetails").Range("A1").Resize(srcData.Rows.Count, _
srcData.Columns.Count)
dstData.Value = srcData.Value
dstWB.Close SaveChanges:=True
End Sub
You've also confused using ThisWorkbook and later using ActiveWorkbook. It's not clear which on you're saving.
This type of "value only" data copy is very fast, and you may not need to disable events or screen updates. You still may need to disable these if you also have event handlers catching worksheet changes.

Delete worksheets if cells below specified strings are empty

I am trying to write a script which will cycle through the worksheets in my workbook and delete the worksheet if the cells directly under the strings "detected", "not detected" and "other" are empty. If there is something entered under any of the three strings the worksheet shouldn't be deleted.
I have some code (below) which will delete the worksheet if a specific cell is empty, but I need to integrate a piece to FIND any of the three strings (if they are there, they will be in column A), and to offset this to check whether the cell below is empty.
Sub DeleteEmptyWorksheets()
Dim MySheets As Worksheet
Application.DisplayAlerts = False
For Each MySheets In ActiveWorkbook.Worksheets
If MySheets.Range(“A1”) = “” Then
MySheets.Delete
End If
Next
Application.DisplayAlerts = True
End Sub
The script will be used in processing COVID19 test results, so if you can help it will be extra karma points!!
Thankyou.
Here's a code that should assist you.
Sub DeleteEmptyWorksheets()
Dim MySheets As Worksheet
Dim rngTest As Range
Dim arTest
Dim blNBFound As Boolean
arTest = Array("detected", "not detected", "other")
Application.DisplayAlerts = False
For Each MySheets In ActiveWorkbook.Worksheets
blNBFound = False
For i = LBound(arTest) To UBound(arTest)
Set rngTest = MySheets.Range("A:A").Find(arTest(i))
If Not rngTest Is Nothing Then
If Len(rngTest.Offset(1, 0)) > 0 Then
blNBFound = True
Exit For
End If
End If
Next i
If blNBFound = False Then MySheets.Delete
Next
Application.DisplayAlerts = True
End Sub

Resources