Excel VBA Range 'Delete' method randomly fails - excel

Background
I have a piece of VBA code which deletes multiple rows on a worksheet depending on if the values on each row are TRUE or FALSE in a specific column (a 'control range'). The worksheets as switched as a master loop (above the level of this function) that cycles through multiple sheets and workbooks.
This is used in the Excel 2013 and 2016
Naturally the code searches for matching rows and builds up a range object and only once the loop has ended is that rage deleted.
Code extract
I can't send a copy of the actual workbook because it is too large, too complicated and I don't have time to explain how it works - besides it is confidential.
I have listed below an extract of the key code that is failing (with the command that fails in bold).
' Build up a list of rows which are valid
For Each rngCurControlCell In rngSheetControlRange.Cells
If rngCurControlCell.Value = True Then
If rngRowsToDelete Is Nothing Then
Set rngRowsToDelete = rngCurControlCell.EntireRow
Else
Set rngRowsToDelete = Union(rngCurControlCell.EntireRow, rngRowsToDelete)
End If
End If 'rngCurControlCell.Value = True
Next rngCurControlCell
' Delete the rows
If Not rngRowsToDelete Is Nothing Then rngRowsToDelete.Delete
Problem / Issue
Sometimes this code works and sometimes it does not.
I have put various debugging in the code and can confirm that the code always finds the target rows ('rngRowsToDelete' in the extract above) and always builds up the range object correctly.
HOWEVER ... sometimes the delete works and sometimes it does not - even though it it run against the same worksheet. No error is generated.
Has anyone come across a similar situation / have any thoughts ?

Related

Using variables to select a range of cells

I'm trying to make a section of a small macro in Excel that copies info from some inputs between cells AE13 and AI13. The thing is that I want to make it so that the next row is selected by Excel once the program does its thing (so, once the program copies the content for AE13:AI13 and does some processing, it'll jump to copy the contents of AE14:AE14 and so on as long as it encounters data (for this example, let that be until the variable I'm using reaches 20)). For this I'm doing the following:
Do while Active < 20
Active = 13
'The code that does the cleanup from the prior run goes here
Range("AE" & Active & ":AI" & Active).Select
Selection.Copy
'Then here goes the rest code that does the actual program, which has been running fine prior to implementing this "Active" variable (which is not used anywhere else in the code).
Active = Active + 1
Loop
To me that's how it's supposed to go, but when I try to run this, Excel selects rows AE:AI, it activates all the cells in those columns instead of the ones in the row I'm specifying.
Could anyone help me see if I'm doing something wrong?
Kudos from a ramdon, troubled gen z trying to survive in the workplace.

Managing Excel Worksheet_Change Feature

I have created a spreadsheet which uses the Worksheet_Change feature and the code associated with that works very well. I can stop it firing unnecessarily when inside the module by using Application.EnableEvents = False.
However, while I've created a form to enter data directly into the next available row (again, that works fine in terms of entry) it doesn't cause the formulae in the sheet to calculate (even though auto calculation is on and re-enabled within the module). If I manually place my cursor in the row, hit F2 and simply press enter, everything then fires up.
I have tried to enter data directly into the cells, but of course the Worksheet_Change feature then kicks in again and the cursor isn't simply moving to the next adjacent cell ....
I've tried to check firs for any direct entry with the code below and if it looks like the user isn't entering directly into the cell, the Worksheet_Change is disabled:
Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo eventhandler
Sheets(1).Range("a1").Select
LastCell2 = Sheets(1).Cells(Rows.Count, "A").End(xlUp).Row
Dim intersection As Range
Set intersection = Intersect(Target, Range("A3:F" & LastCell2))
If intersection.Row = LastCell + 1 Then
Exit Sub
End If
Application.EnableEvents = False
The code above is simply checking to see if data is being entered into the next empty cell and if that's the case I want it to just exit there but it isn't working.
So I actually have 2 problems :
the first is why this formula isn't triggering after entry via a vba form - I've used INDIRECT since there are other macros that delete rows by moving the remaining cells up and that was causing the count in the $A$3:$A$500 to reduce to $A$499 and then 498 etc - the addition is done depending on the system date and the transaction date so I get a current value and a future value using a standard sum statement:
=AD1-(SUMIF(INDIRECT("$A$3:$A$500"),"<="&TODAY(),INDIRECT("$E$3:$E$500")))+(SUMIF(INDIRECT("$A$3:$A$500"),"<="&TODAY(),INDIRECT("$F$3:$F$500")))
The second is why I can't enter data directly into the spreadsheet and trap the fact that I don't want it to do anything and simply allow the user to hit enter and move to the next adjacent cell to the one they just entered data into.
Is this a lost cause and am I trying to do too much here? I'm relatively new to coding and teaching myself so apologies if the standard and style isn't to everyone's taste.
Thanks in advance for any replies.

How to copy specific parts of a table from a sheet to another

I'm trying to get some details copied in Excel from Sheet 1 columns 1-5 to Sheet 2 columns 1-4, but only for lines that include text or values on sheet one under a specific column (in this case, Column 2). There are other columns in between, so I need to be able to use exact columns rather than A:D for example.
Example of what I'm trying to achieve:
I have tried using a simple IF function with A:A<>"" so it would include any rows that have any data in them, however this does not seem to copy as I need and occasionally based on my attempts i also get circular reference errors. Additionally, I’m not sure how to make sure this gets pasted at the bottom of a table that will expand with each addition.
I realize a probably easier option would be to simply copy Sheet 1 entirely and use a filter on row 1 to deselect Blanks on A:A, but the sheet has so much more info that it would be a waste, and additionally info is constantly added so I need something scale-able. It also occurred to me now that by doing this i would include info from the "header" and "footer", basically a frozen pane - which I do not need.
Could this be done via a simple function, or would it require a Macro?
Please keep in mind I'm rubbish at programming, just trying to make my life easier and learn as I go. A lot of excel forums help but still I'm no coder. I can understand to a pretty big degree what the code does and can adjust accordingly though :)
As suggested, this cannot be done with formulas. There are different ways to achieve this.. below is one approach:
Sub CopyFilteredRows()
Dim oSourceSheet As Worksheet: Set oSourceSheet = ThisWorkbook.Worksheets("Sheet3") ' Set your source sheet here
Dim oRng As Range: Set oRng = oSourceSheet.Range("A2:E" & oSourceSheet.Range("C" & oSourceSheet.Rows.Count).End(xlUp).Row)
' Set filter on column B
oRng.AutoFilter
oRng.AutoFilter 2, "<>"
' Copy to specified sheet
oRng.SpecialCells(xlCellTypeVisible).EntireRow.Copy ThisWorkbook.Worksheets("Sheet4").Range("A2") ' Change your destination sheet here
' Clear objects
Set oRng = Nothing
Set oSourceSheet = Nothing
End Sub
Paste the above UDF in a Module and then run it whenever you want to perform the copy. I suspect you would have to modify it a bit so that you can cater for your particular scenario but it should give you a start

Deleting Items from Listbox - Runtime Error 381

I am new to VBA and have been hacking together code from various examples and tutorials around the web. I'm aware that this will mean my code is hideous and inefficient, but I'm focusing on getting things to work right now and learning to clean up later.
I'm stuck on the part of my task that involves making an 'address manager' to store modifiable lists of recipients for daily email tasks. I created a userform to act as the manager, and it works fine to add files (user fills in textbox and clicks add, item is added to listbox and to relevant sheet in the workbook) and deletion works fine to a point (user selects item from listbox, clicks delete, item is removed from listbox and source sheet, and the list is repopulated.)
I can add and delete items freely, and the rest of my program interacts properly with the lists, but for some reason there's a weird problem I can't find the source of. When I created the file to test, I added 2 email addresses to each tab that contains a recipient list. I can add recipients and they show up perfectly, and I can also delete them without issue. The problem occurs when I try to delete one of the last two entries (regardless of what they are) I will get a Runtime Error 381 - Invalid Property Array index.
The debugger points me right at the starred part of the following code, which is the code I use to populate the list. It works fine as long as there are more than 2 entries for each. As soon as one of the last two entries are removed, the runtime error occurs and I can't even open the userform unless I go and manually add a second entry to the source sheet. I'm sure I`m missing something simple, but I really appreciate any help you may have.
Sub FillFS4ListBox()
Dim rng As Range
Me.MultiPage1(0).FS4listbox.Clear
With wb.Sheets("FS4")
Set rng = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp))
**Me.MultiPage1(0).FS4listbox.List = rng.Value**
End With
End Sub
Me.MultiPage1(0).FS4listbox.List = rng.Value
Using Value on a single-cell range doesn't produce an array, just a single value. If List expects an array then you'll need to check your input range to see if it's a single cell, then wrap that cell's value using (eg) Array()
E.g. - putting this in a function:
Function GetList(rng As Range)
GetList = IIf(rng.Count = 1, Array(rng.Value), rng.Value)
End Function
Usage:
Me.MultiPage1(0).FS4listbox.List = GetList(rng)

Referencing Excel Sheets with JET Driver Sheets Are Duplicated with Underscores

I'm referencing an excel document with the JET database driver, which was working just fine until one day the application failed. Upon further investigation I noticed that the tabs were duplicated in some instances (all tabs actually) - i.e. Tab1$ and Tab1$_. I've researched this issue and found that it is caused by the user applying a filter. Now the filters have been removed, no special formatting, frozen panes, or print formats, but still I have these tabs duplicated. Normally I'd code around this, but since we're in a code freeze I need to come up with an Excel based solution. I want to get rid of those crazy underscored tab names / reverences. I could probably run a program to clean up the file if necessary, to send it back to the users, but I want to explore Excel options first. Thoughts? I have Excel 2010, and access to any other version as well.
The underscore "sheet" is a named range. Is it possible for you to run VBA? if so:
Dim defName As Name
''Either
With ThisWorkbook ''Entire workbook
For Each defName In .Names
MsgBox defName.Name
defName.Delete
Next
End With
''Or
With Sheets("Sheet1") ''Scoped to sheet only
For Each defName In .Names
MsgBox defName.Name
defName.Delete
Next
End With

Resources