Curious Delete Behavior with Command Button VBA - vba

I am continuing my efforts with data pulled from a mainframe. Currently, I am continuing work on sorting data for use in forms and potential data processing and the like. The data is alphanumeric and is similar in form to one of my previous questions related to my continuing data efforts.
One of my current development lines involved increased usability in the form of macro-enabled buttons. One such button involves a macro which is intended to delete all data in one column "A" from A2 to the end of any existing datarows in the sheet.
The code is as follows:
Sub DeleteCriteria_Click()
Dim CriteriaRange As Range
Dim LastCriteriaCell As Long
With Sheets("Criteria")
LastCriteriaCell = .Range("A" & Sheets("Criteria").Rows.Count).End(xlUp).Row
Set CriteriaRange = .Range("A2:A" & LastCriteriaCell)
End With
CriteriaRange.Cells.Select
Selection.Delete
End Sub
Curiously, this code ends up shifting my columns over by one each time I activate the button, and ends up deleting my header and subsequent columns with repeated clicks. This behavior resembles that of a normal delete function for a column. Refactoring the range commands CriteriaRange.Cells.Select | Selection.Delete into the forms CriteriaRange.Cells.Delete and CriteriaRange.Delete does not correct this issue.
My intent is to completely delete the entries so that there are no blanks or leftover datasets when new criteria is entered after the entries are deleted. I thus have two questions:
1) What is causing this behavior, i.e. what I am doing incorrectly, here?
2) How do I correct this behavior to utterly delete the cells or functionally perform the equivalent, thereby prevent any references to blank or null cells, while retaining my column?

Change your code to
CriteriaRange.Delete Shift:=xlUp
The default is
CriteriaRange.Delete Shift:=xlToLeft
Because of this your columns are moved.
Your code can be written as
Sub DeleteCriteria_Click()
Dim LastCriteriaCell As Long
With Sheets("Criteria")
LastCriteriaCell = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> This is required so that your header cells are not touched
If LastCriteriaCell < 2 Then Exit Sub
.Range("A2:A" & LastCriteriaCell).Delete Shift:=xlUp
End With
End Sub
OR
Sub DeleteCriteria_Click()
Dim LastCriteriaCell As Long
With Sheets("Criteria")
LastCriteriaCell = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> This is required so that your header cells are not touched
If LastCriteriaCell >= 2 Then _
.Range("A2:A" & LastCriteriaCell).Delete Shift:=xlUp
End With
End Sub

Related

Deleting Rows From Filtered Range Via Macro

I am having issues with the below code, which is trying to filter a set of data, then delete the visible rows. Currently I get a "Run Time 1004 Error: Delete Method or Range Class Failed" which occurs on the last line of my code. I found a similar question on the site, and the answer appears to be exactly what I have in my last line of code.
Dim LastRow As Long
LastRow = Worksheets("Orders").Range("A" & Rows.Count).End(xlUp).Row
Worksheets("Orders").Range("A1:CU" & LastRow).AutoFilter Field:=10, Criteria1:="New"
If Worksheets("Orders").Range("A1:CU" & LastRow).SpecialCells(xlCellTypeVisible).Count > 1 Then
Worksheets("Orders").Range("A1:CU" & LastRow).Offset(1, 0).SpecialCells _
(xlCellTypeVisible).EntireRow.Delete
Later in my code, I filter the same set of data again, this time deleting the non-visible (filtered out) rows. I am also getting the same error on the last line of this code as well:
Worksheets("Orders").Range("$A1:CC" & LastRow).AutoFilter Field:=26, Criteria1:= _
"=*Jazz*", Operator:=xlAnd
Dim oRow As Range, rng As Range
Dim myRows As Range
With Sheets("Orders")
Set myRows = Intersect(.Range("A:A").EntireRow, .UsedRange)
If myRows Is Nothing Then Exit Sub
End With
For Each oRow In myRows.Columns(1).Cells
If oRow.EntireRow.Hidden Then
If rng Is Nothing Then
Set rng = oRow
Else
Set rng = Union(rng, oRow)
End If
End If
Next
If Not rng Is Nothing Then rng.EntireRow.Delete
Any help on these errors would be much appreciated!
You dont need to invoke the SpecialCells before deleting, because the method Delete acts only on the visible rows. The problem might be due to this.
Besides, the test .SpecialCells(xlCellTypeVisible).Count > 1 is useless because the header row of the filtered range remains visible.
Here's a safer and simpler way to write your code:
With Worksheets("Orders").UsedRange
.AutoFilter 10, "New"
.Offset(1).EntireRow.Delete ' <--- no need for .SpecialCells
End With
Post by #A.S.H is a great illustration of minimalism, but your 1st code block is still fine.
Just to make a small correction, change .SpecialCells(xlCellTypeVisible).Count > 1 to .SpecialCells(xlCellTypeVisible).Count > 2 as pointed out by him. Also, don't forget to add the line Worksheets("Orders").ShowAllData at the end.
The 2nd code block is unnecessarily complicated (and hence likely error-prone). Instead, simply change the filter of the 1st code block to Criteria1:="<>New" if you want to eliminate other than "New" items.
The Run Time Error issue seems to be due to something else. Make sure the sheet is not protected.
To see if it's the code or the file format that's causing the problem, you can also test the same code on a new workbook copying just the data (paste value) from your existing one and then run the code.
You should remove any filters at the top of your code.
On Error Resume Next
If Worksheets("Orders").AutoFilter.FilterMode = True Then
Worksheets("Orders").ShowAllData
End If

Use VBA to replace sporadic #N/A cells with a formula

I have data that comes from different sources via Get Data/Connections that goes into a sheet/table called RawData. I have created a macro linked to a button the user must click to fill in some of the data in RawData with an index/match function that points to another workbook where the reservation number from RawData is matched to the other workbook to determine the length of stay.
I am not appending said workbook to the RawData table for different reasons. I can go that route if need be but I figured there would be an easier route before we cross that bridge. The issue I have is that once the macro is ran, the other workbook, at times, may not have the reservation data. In these cases, I had to manually determine this data.
This new data can be placed within my main workbook [but I currently have it in it's own workbook (LOSNAintoActualLOS.xlsm) as I've been running tests on making this work]. And the formula has to be pasted into the table because when the table refreshes, the row of data that would normally have the length of stay removes the formula and replaces it with it's original value, a blank cell.
What I need is for my code to loop through all the cells within the F column of a table, determine the cells with #N/A errors, then paste a formula in the error cell. I have done some research and can't seem to find something that suits my needs. I attempted doing this as a loop but seeing as I'm still pretty new to VBA coding, it's definitely not my strong suit.
Sub Macro2()
Dim r As Integer
LastRow = Range("B" & Rows.Count).End(xlUp).Row
With Worksheets("Sheet1").Range("F2:F" & LastRow)
For r = 2 To LastRow
If .IsError(Worksheets("Sheet1").Range("F" & r)).Value Then
.Formula = "INDEX(LOSNAintoActualLOS.xlsm!Table1[#Data],MATCH([#Reservation],LOSNAintoActualLOS.xlsm!Table1[Reservation],0),7)"
.Value = .Value
End If
Next r
End With
End Sub
When I run the code for my If statement I get Run-time error '438': Object doesn't support this property or method. If I remove the first period from .IsError I get Compile error: Invalid qualifier.
IsError is not part of Worksheets("Sheet1").Range("F2:F" & LastRow)
Switch it up like this.
Sub Macro2()
Dim r As Long
Dim LastRow As Long
LastRow = Worksheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
For r = 2 To LastRow
With Worksheets("Sheet1").Range("F" & r)
If IsError(.Value) Then
.Formula = "INDEX(LOSNAintoActualLOS.xlsm!Table1[#Data],MATCH([#Reservation],LOSNAintoActualLOS.xlsm!Table1[Reservation],0),7)"
.Value = .Value
End If
End With
Next r
End Sub

Moving data from one workbook to another when a certain field is completed

I have looked at numerous other posts but have not been able to find a workable solution to a problem I am having. Firstly, I am a total newbie with VBA and I do mean total.
I have a spreadsheet where a date is input when we successfully make contact with someone. This data then needs to be cut and pasted onto a master archive so we can prove we have called them if required. What I need is a way to cut and paste the whole line the data is on, onto a workbook which will store the data. My plan is to have 7 workbooks feeding into one master but the master can have 7 tabs if that makes things easier. I can supply the spreadsheet I am working on if required.
I have tried the following code but it seems to copy a row above each time leading to blank rows on the master sheet (they're actually showing as gold but i think that's to do with the formatting of surrounding cells)....
Sub deleterow()
'Using autofilter to copy rows that have a completed date field to a new
worksheet
Dim LR As Long
Range("A3").EntireRow.Insert Shift:=xlDown
LR = Sheets("Sheet1").Cells(Rows.Count, "M").End(xlUp).Row + 3
LR1 = Sheets("Sheet3").Cells(Rows.Count, "M").End(xlUp).Row + 1
With Sheets("Sheet1").Range("M3:M" & LR)
.AutoFilter Field:=1, Criteria1:="<>", VisibleDropDown:=True
.SpecialCells(xlCellTypeVisible).EntireRow.Copy
Destination:=Sheets("Sheet3").Range("A" & LR1)
.SpecialCells(xlCellTypeVisible).EntireRow.Delete
End With
End Sub

Copy formula from a specific sheet and cell and drag it down until specific column last row

So far I have this code below; counting last cell is working fine but is copy/pasting the wrong data to wrong sheet. Should copy data and use the formula from Sheet "Parsing" cell B2, and its using the main sheet where is the VBA. Looks lile what is missing is to execute the copy/select to "parsing" sheet, but didnt manage to do it.
Sub drag_formula_original()
Dim myLastRow As Long
With Worksheets("Parsing")
myLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range("B2").Copy Destination:=.Range("B2:B" & myLastRow)
Application.CutCopyMode = False
End With
End Sub
Its solved. Thanks a lot.
Range("B2").Copy
The above will grab by default from the Activesheet
you have to tell it what sheet you would like it to pick that range/value from.
sheets("Parsing").Range("B2").Copy
Edit: Just noticed your With
To actually use a with you need to use a "." e.g. your copy line would look like below
.Range("B2").Copy
One other thing to note this:
Range("B2:B" & myLastRow).Select
ActiveSheet.Paste
Is rather inefficient, below would be better. Selecting in general is best to keep away from it is rather slow
Range("B2:B" & myLastRow).Paste
Or with your with
.Range("B2:B" & myLastRow).Paste
I just copied and pasted your code and ran it. I changed nothing in your code except for adding "Option Explicit" before your sub. (Just a personal habit)
Option Explicit
Sub drag_formula_original()
Dim myLastRow As Long
With Worksheets("Parsing")
myLastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
Range("B2").Copy
Range("B2:B" & myLastRow).Select
ActiveSheet.Paste
Application.CutCopyMode = False
End With
End Sub
I did, however, use a very simple formula in cell B2. What I did was have column A go from 1 to 10 and column C go from 11 to 20. Cell B2 was =A2+C2.
After running the code I checked each cell in column B and they each had the correct formula in them, and not a hard-coded value.
A trick I do when I want to do something like this but can't figure out how is I record a macro of me dragging the cell formula down a little ways and then stop the recording and look at the code it made. From that you should be able to adjust it to do what you want.
When I did that I got this code:
Sub Macro1()
'
' Macro1 Macro
'
'
Range("B2").Select
Selection.AutoFill Destination:=Range("B2:B15"), Type:=xlFillDefault
Range("B2:B15").Select
End Sub

Insert new row in the same place in two sheets > copy formulas from above

I've created a tracking document for my workplace, but my limited knowledge of Excel has only taken me so far. Hoping there's someone out there who enjoys cleaning up messy workbooks...
I have a document with two connected worksheets: 'Annuals', covering a lot of detail about the forms I'm designing; and 'Summary', which is really intended for management use. All the information in the 'Summary' page is a cell reference to 'Annuals' and the 'Summary' page is normally password protected so that the formulas can't be overwritten. You can download a dummy copy of the larger document I'm hoping to implement: Dropbox Link We use Excel 2010 at work, although the attached document was last edited in OpenOffice Calc.
The basic function of this document is to present varying degrees of information per worksheet, with most raw information being manually provided. I would like it to be dynamic enough that the user doesn't need to understand the importance of keeping cell references - they can just press a button to add their task to the list, and the program will populate the rest behind the scenes.
Aside from the terrible way that I've visually indicated the row label "hierarchy" in column C, I'm also having issues when someone wishes to insert a new row in the 'Annuals' page; I have not found an effective way to insert a row on the 'Summary' page at the same time while maintaining dynamic formulas and formatting. It has been difficult to write a macro to do this because I only want certain cells referenced on the 'Summary' page (although I'm 100% sure there's a way to do this).
This is my attempt:
Public sAddress As String
Sub AddRow()
R = ActiveCell.Row
ActiveCell.Offset(-1).EntireRow.Insert Shift:=xlDown
Range("E" & R & ":G" & R).Copy Destination:=Range("E" & R + 1 & ":G" & R + 1)
Range("T" & R).Copy Destination:=Range("T" & R + 1)
End Sub
Sub DeleteRow()
ActiveCell.EntireRow.Delete
End Sub
Sub AddSummary()
On Error Resume Next
Worksheets("Summary").Activate
If sAddress > "" Then Sh.Range(sAddress).Select
R = ActiveCell.Row
ActiveCell.Offset(-1).EntireRow.Insert Shift:=xlDown
Range("E" & R & ":G" & R).Copy Destination:=Range("E" & R + 1 & ":G" & R + 1)
Range("T" & R).Copy Destination:=Range("T" & R + 1)
End Sub
Sub Variab()
sAddress = ActiveCell.Address
End Sub
Sub Everything()
Call AddRow
Call Variab
Call AddSummary
End Sub
Maybe a pivot table could be implemented? However, I have no idea how to make a pivot table actually work, let alone make it user-friendly or pretty. I tried - and failed - to make a pivot table that I could reference in the Summary page and hide from other users, but I didn't get very far.
I know that you're probably shuddering at my workbook, but if you can think of better methodology behind the information I'm trying to track (amongst many users, with varying degrees of computer literacy) then please let me know!
Click on Summary tab
Shift-click on Annuals tab
Insert the row.
That's it! It will insert a blank row on both sheets.
If you want to copy data from an existing row into the newly created row (as in your macro), select both tabs as above, highlight a row, copy it, and paste it into the new row. You will see that the copy command was applied to both sheets, just as if you had done the copy command on each sheet.