How to delete a row instead of hiding it? - excel

Trying to delete, rather than hide from one worksheet (where the filter button is to another where the catalogue list is. i.e. trying to create something like (best way to describe this) a shopping basket based upon the users selection and reducing the (long) list on the other worksheet after selection.
I am beginning to pull my hair out on this one and after having read and watched many, many articles on deleting rows after filtering on empty cells and today nothing has really helped as there are more issues than solutions when following codes from other, thus far.
Basically, I have a Hugh catalogue on a separate worksheet and if the user says yes, this should be shown and if not if blank (but with a value) it should be deleted. See so very basic script I have that works perfectly, but I have to delete and not hide. It appears EntireRow.delete is something beyond me, as it introduces many many issues, where hide simply worked so smoothly.
Trying many other scripts, they all really fail in simplifying the answer and 99% are actually for a single worksheet and range rather than a specific worksheet and specific columns i.e. E:E (script script below shows more) I am using a table too, so this is a little different too.
For a = 2 To 150
If Worksheets("Requirements").Cells(a, 5).Value = "High" Then
Worksheets("Requirements").Rows(a).Hidden = True
End If
Next
Anyone with a brilliant one or two liner to delete rather than hide, or delete all hidden if necessary
Many thanks in advance

Consider:
Sub sjdhfs()
For a = 150 To 2 Step -1
If Worksheets("Requirements").Cells(a, 5).Value = "High" Then
Worksheets("Requirements").Cells(a, 5).EntireRow.Delete
End If
Next a
End Sub
Note we run the loop from the bottom to the top.

Related

Application.Caller returning incorrect row number

I have the following code:
Set b = ActiveSheet.Buttons(Application.Caller)
With b.TopLeftCell
bcn = .Column
brn = .Row
End With
Most of the time it works flawlessly. However, sometimes when this is called the row number returned is off by +14. There are no hidden rows in the sheet.
When this happens, if you leave the worksheet open for several minutes and do nothing, it will start working again.
What is happening, how can I fix it, or is there a better way to get the row number?
The problem seems to be that if you leave the default name on your Buttons, it's quite probable that you'll have duplicate names and Application.Caller will just return a non-unique name, failing to return the correct Sheet name you need.
You can avoid this by using custom names and by renaming your Buttons with a naming convention, like SheetName + Button + Counter (e.g: Sheet1Button1).
Hope this helps.
The reason why this was happening was due to multiple buttons on top of each other. Occasionally, a background button (that shouldn't have been there at all) became the foreground button and was the source of the unexpected behaviour. Removing the duplicate buttons solved the problem.
This only became apparent when trying to programmatically rename buttons, which manifested by trying to give multiple buttons the same name and a permission denied error raised, as the name was based on row and column number.
The issue only happened about 1 in every ~20 opens so it was not a big enough problem to cause major concern; hence why it took 6 months to solve.

Table extending instead of creating

I have a bug in my excel sheet that appears on other computers I can't reproduce on my machine.
I made a sub that takes data from a database and create tables in Excel. In this case it's mining projects.
It picks the first cell, finds the first empty cell when going to the right, writes the header, makes a table with it then fill it with another sub.
When a coworker tries to use it, it extends the previous table then crashes while trying to make the new one, as two tables can't overlap.
Initial Layout:
What's supposed to happen:
What my coworkers get:
Public Sub creerTable(Nom As Variant)
Dim cellule As Range
' se placer
Set cellule = ActiveWorkbook.Worksheets("DATA").Range("A1").End(xlToRight).Offset(0, 1)
Do While cellule.Value <> "" Or Not IsEmpty(cellule)
Set cellule = cellule.Offset(0, 1)
Loop
'cr?er le header
cellule.Interior.Color = vbBlue
cellule.Value = Nom
'cr?er la table
ActiveSheet.ListObjects.Add(xlSrcRange, cellule, , xlYes).Name = Nom
End Sub
EDIT: After more testing on my coworkers' computers, the problem is likely linked to an Excel setting. When something is written to the right of a table, the table extends to cover it. Googling revealed this to be an auto-correct behavior. I guess I'll have to deactivate that option of auto-correct.
The answer was really dumb. The problem is an autocorrect setting in excel. All I had to do was add this line:
Application.autocorrect.AutoExpandListRange = False
It's not clear how this code could possibly work on your machine, but not your co-workers. I suspect that the inputs must somehow be different, but that is for you (having access to the inputs, which we do not) to work out on your own. Generally: inconsistencies cannot exist, so when one appears to exist, examine your inputs and you'll usually find there is a discrepancy in the input data which causes the divergent output.
I'll note that The End method of range objects may not be reliable, in particular I observed things like Range("A1").End(xlToRight).Address yields "B1" in the following scenario where column A, B and C are each separate ListObject tables:
And ALSO in this scenario:
It seems like you try to find the next empty cell/column (which may be between two or more non-empty cell/column). It should be trivial to do this, but we need to understand that next is relative to what existing thing on your worksheet?
Are you're trying to find the next empty cell after a ListObject named "Tâches" (or cell value = "Tâches")?

Excel Print Area

I would like to be able to print everything I have from columns A:H in landscape mode, and I was wondering if anyone knows how to do this such that whenever you open this specific document and try to print it, it will automatically print under these specific settings. Additionally I would only like to print where there actually is text and avoid printing the white space (I have equations filled in all cells A1:H50, but I only actually have numbers filled in RIGHT NOW (but this will change over time) on cells A1:H30. i.e. A31:H50 are for now all filled with the empty space character "")
Additionally, the top row of my document has headers, which I would like to be displayed for every page that I print out. (i.e. headers of stock name, stock price, stock price 1 year ago, and then those columns are filled with 30 stocks). I would like it so that if I have 4 pages (variable) worth of information that end up being printed, that the top row of stock name and price always get printed at the top of each page.
Thanks a lot!
You could use a BeforePrint event to reset the print area to your specifications each time the user tries to print it. No matter what settings the user tries to choose, it would override with the ones you specify in the event code. Try putting the code below in the ThisWorkbook module:
Private Sub Workbook_BeforePrint(Cancel As Boolean)
Application.PrintCommunication = False
With ThisWorkbook.Sheets("Sheet 1")
.AutoFilterMode = False
.Range("$A:$H").AutoFilter Field:=1, Criteria1:="<>", Operator:=xlFilterValues 'if column A (Field:=1) is blank then hide those rows before setting print range
With .PageSetup
.Orientation = xlLandscape
.PrintArea = "$A:$H"
.PrintTitleRows = "$1:$1" 'change to whichever row numbers you want to print on every page
End With
End With
Application.PrintCommunication = True
End Sub
The potential upside/downside to doing it this way would be that it doesn't allow the user to print it in any format other than the one you specify. If you didn't want to limit the user's ability to print it in different formats, you could use the same code inside a non-event Sub and have the user run that macro whenever they need to print it out with these settings.
Okay you're asking a few different questions, and some are easier to answer than others.
Firstly, you want to set a specific area (A1:H50) to be printed every time someone prints the page, and you want it to print in landscape. This is simple - go to the Page Layout ribbon, select the area A1:H50, and click Print Area -> Set Print Area. Then right beside that, click Orientation -> Landscape.
Your third question, about setting a header, is also simple. Go to the Page Layout Ribbon again, and click on Print Tiles. You can either click on the Sheet tab and tell it to repeat some rows at the top, or you can click Header/Footer and manually type in the headers yourself.
Your second question does not have a simple, automated approach (that I know of. Either accept the fact that blank space will be included in the printout (which is fine anyway, as you likely want each page to be spaced the same anyway, regardless of how many rows are filled), or manually "Hide" blank rows.
VBA automated solutions would be possible here, but I don't recommend that you use an automated solution which you don't understand over something so trivial to do manually.
Note that this question is not really suited to this site. This is a question better suited to superuser.com, which is part of the same group of sites as stackoverflow.com, but is geared towards non-programming questions about software - especiallly Excel.

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)

How to Restrict Ctrl + End in an Excel Sheet

I have some data inserted at Rows 500 - 503. I placed the data intentionally at those rows because these rows will be used in Macro's and not for User's view. The data concerned to the user ends at Row 100.
I have hidden the Rows 500 - 503, yet after hitting Ctrl + End, the Cursor moves to Row 499.
My requirement is after hitting Ctrl + End, the Cursor should be at the last cell of Row 100.
So, how do i do this ?
EDIT : Thanks for all the answers. Many advised me to have another sheet for non user related data, but i can't have it. Also i am not supposed to have the vba scripts.(Should have given you these conditions before... my bad!)
This problem will be removed with better isolation.
That is, worksheets which are designed for use by a user should be restricted to containing only the elements necessary for the user interface. In this case, only the rows which the user is supposed to see.
Any data which needs to be persisted in worksheets which is not designed for direct user consumption should be on their own worksheets, which can even be hidden from the user completely.
The specific answer to your question of course is: trap the usage of the Ctrl-END key.
You can do this easily by specifying the following event triggers to your sheet:
Private Sub Worksheet_Activate()
Application.OnKey "^{END}", "SuppressMe"
End Sub
Private Sub Worksheet_Deactivate()
Application.OnKey "^{END}", ""
End Sub
and another module containing
Sub SuppressMe()
' you can be very creative here about line 100 or not 100
MsgBox "Co-Cooooo :-P"
End Sub
Another cute way meeting the requirements you described and eliminating the need of watching and suppressing keys would be to limit navigation to row 100. Now a Ctrl-END would place the user into the rightmost column of row 100, and Ctrl-DOWN would be covered as well. In fact the user just can't go past row 100
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Row > 100 Then
Me.Cells(100, Target.Column).Select
End If
End Sub
but .... wait !!! is there really no way? ... of course the user still may SCROLL past row 100 and detect your little row-500 easter egg. So I concur to 100% with earlier suggestions about a different strategy, because
a user finding out that exactly line 500 - 503 is hidden can become tremendeously curious about the why's
Ctrl-END is not the only way the user can navigate past row 100 - you would need to suppress END-DOWN (a 2 - key combination ... you need to buffer the END and ask the next key: are you a DOWN ... have fun!)
and you are wasting disk space to store a sheet with so many blank rows just for that line 500
You may have reasons to implement a key supressor, but always remember there are many different ways for the user to bypass it and this needs to be considered very carefully.
That's Excel's built-in behaviour, and I don't think you can change it. Suggestions:
Put your hidden data on another sheet of the same workbook. This is really the cleanest way to work.
Alternatively, navigate using CtrlDown arrow or EndDown arrow instead of CtrlEnd.
As others said it's certainly better to separate your non-user data on a different sheet.
That said, one thing you could do is protect your sheet and disallow access to locked cells, leaving only the cells in which the user has to input something unlocked.
Doing that prevents CtrlEnd from doing anything at all: it can't jump to the last cell as it is locked, so it doesn't do anything. (Tested on Excel 2007)
But again, you'll probably be better off by separating user and non-user data in different sheets.

Resources