Clearcontents of range without selecting it - excel

I am trying to clear contents of whole range with using .End to specify my range so i reduce the hassle of specifying the range each time for each sheet.
Here is the code :
Public Function clear(ws_clear As Worksheet, first_cell As String)
ws_clear.Range(first_cell).End(xlToRight).End(xlDown).ClearContents
End Function
But this does not work and i dont know how to clear all non-empty cells from a single cell in the corner.
Thanks for your help.

Related

How to change a cell value based on active/selected cell

I am having a list of names in a Range A2:A77, in the worksheet name called Manual. whenever i choose a name, that is when a cell gets selected from the range, that active cell value should get reflected in the cell C1. Also, the macro should not work incase if i selected else where, other than the given worksheet or range.
I have googled alot but nothing seem to be matching my criteria, so i'm here, hoping for a better solution. You may ask me to achieve this by using data validation, but for that i will have to do multiple clicks and scrolling work to be done everytime. so to avoid that i'm looking for vba code to minimize the work and time.
Thank You.
I am only just learning VBA at the moment so this could be some very horible code but here goes.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim cells As Range
Set cells = ActiveSheet.Range("A1:A27")
If Not (Intersect(Target, cells) Is Nothing) Then
ActiveSheet.Range("C1").Value = Target.Value
End If
End Sub
Worksheet_SelectionChange is called if the selected cell in the sheet changes then using the test from InRange that I found here: VBA test if cell is in a range test if the cell is within the defined range then set the values.
Edited as sugested by #Vitaliy Prushak in comments.

Can I set a dynamic range in vba excel to use in filter

The following excel sub is a filter that is filtering out rows based on the rows in the criteria row.
The code works well when the ranges are set with absolute data. I want to change the code to take the range from references stored as cell values (an indirect reference) but I cannot find a way to adapt other code snippets I see to work and I wonder if anyone can help me. I am not a programmer.
The problem is that as new data is inserted from time to time the range reference will move and the start of the data an the associated filter is in cell (using RC notation 14,14) and the data in cell 13,12. While I know I can’t use the indirect function in vba I wondered if there is a way to dynamically assign a range to be able to use the Advance filter function.
I have the code to find the last column and row of the data block.
I have tried the following code (2 attempts) but it won’t let me use the object in this way
I have tried to crate the cell reference as a string then assign it using the range function. I then read an answer where someone had put the value of the cells directly into the range function and it has worked for them ( they were copying cells). The 2 attempt are broadly the same but in the second I am trying to be more specific.
The issue seems to be as soon as I change from an absolute reference "A50" in the range statement the range no longer works. I am unsure how to resolve this and perhaps it can't be
It may be helpful to know the that data being filtered is rows of name and telephone data along with a tally system to show attendance (one column per week for a year)
The cells with the dynamic data hold them in the form A1 not RC format
Sub UseAdvancedFilterInPlace()
'This version of the sub has absolute references and works perfectly
Dim rdData As Range
Dim rgcriteria As Range
Call TurnOffStuff
Set rgData = Sheet9.Range(“A50”).CurrentRegion
Set rgcriteria = Sheet9.Range(“A46”).CurrentRegion
rgData.AdvancedFilter xlFilterInPlace, rgcriteria
Call TurnOnStuff
End Sub
Sub UseAdvancedFilterInPlace()
'This version of the sub has dynamic references and fails
Dim rdData As Range
Dim rgcriteria As Range
Call TurnOffStuff
Dim Top_of_data As String
Dim Top_of_Criteria As String
Dim My_range As Range
‘Attempt 1
'Set rgData = Range(Sheet9.Cells(13, 12).Value).CurrentRegion
'Set rgcriteria = Range(Sheet9.Cells(14, 14).Value).CurrentRegion
'Attempt 2
Set rgData = Sheet9.Range(Sheet9.Range(Cells(13, 12)).Value).CurrentRegion
Set rgcriteria = Sheet9.Range(Sheet9.Range(Cells(14, 14)).Value).CurrentRegion
rgData.AdvancedFilter xlFilterInPlace, rgcriteria
Call TurnOnStuff
End Sub
The actual error message I get is an application-defined or object-defined error
This worked for me.
Set rdData = Sheet9.Range(Sheet9.Range("L13").Value).CurrentRegion
Set rgcriteria = Sheet9.Range(Sheet9.Range("N15").Value).CurrentRegion
given that Range("L13").Value is A50 and Range("N15").Value is A46.
extra: Use the statement Option Explicit in the first line of every module, out of every sub or function. This option throws an error on undeclared variables, and will help you avoid renameing mistakes on variables.

Macro added PrevSheet function returns #NAME error

I added a simple Previous Sheet macro to file and it worked normally, until it started to return #NAME error, and i can't figure out why.
I meant to use it with named single cell ranges which are consistent across the workbook, I'd used it successfully before naming the ranges and didn't think it would have any impact on the fuction. After naming the ranges though it no longer works, not even for regular non named ranges.
I have tested this by creating a new workbook, filling some sheets and trying it out, and it still returns a #NAME error. When i evaluate the function, the error appears at the very first step: recognizing the function. However, when i type into the formula bar, the programs offers me the formula normally.
I have also tried referring to the named cells by its cell, and even adding the worksheet name before the cell (eg "prevsheet(previoussheetname!a1), or prevsheet(thissheetname!a1)). I have even, in a last ditch effort, tried adding double quotes before the cell name.
For full disclosure, i have also another macro subroutine that uses references to previous and next sheets, but as it wouldnt recognize the function itself (which should have been an early sign), it makes use of relative referencing (ie activesheet(index - 1, activesheet(index + 1)). At the time i didn't think it would mess up the function, but as i grow ever more desperate and confused, maybe thats a possibility.
the PrevSheet() code i was using:
Function PrevSheet(RCell As Range)
Dim xIndex As Long
Application.Volatile
xIndex = RCell.Worksheet.Index
If xIndex > 1 Then _
PrevSheet = Worksheets(xIndex - 1).Range(RCell.Address)
End Function
And as it is now, as suggested by Chris Neilsen
Function PrevSheet(RCell As Range) As Variant
Application.Volatile
PrevSheet = RCell.Worksheet.Previous.Range(RCell.Address).Value
End Function
As suggested by Chris Neilsen i have edited the named ranges to look like this:
!(nothing)$column$row with its scope set to Workbook
The named range is not available at the range browser.
Only cell B1 is named. It is called "name"
PrevSheet() does not work with either range.
Macros are enabled
Anyone with a better understanding of vba, macros and excel can tell me why this is happening and how do i fix it so it returns the value of the specified cell in the first sheet to the left of sheet the function is typed in? (ie, in sheet4, =prevsheet(A1) will return the value of cell A1 in sheet3)
I hope my question is clearer now!
Your code appears to work if it is placed in a Standard Module:
Public Function PrevSheet(RCell As Range) As Variant
Dim xIndex As Long
Application.Volatile
xIndex = RCell.Worksheet.Index
MsgBox xIndex
If xIndex > 1 Then
PrevSheet = Worksheets(xIndex - 1).Range(RCell.Address)
End If
End Function
For example, in the worksheet:
I have assigned cell A7 the Name junk and the 666 is the value in the previous sheet's cell A7.
This will work, if you define your Named Ranges correctly. There are several ways this can be done, but here's one that is IMO simplest.
Since you say ...use it with named single cell ranges which are consistent across the workbook. you can create a single Named Range, Workbook scope, that will refer to a cell (or cells) on the sheet which references the name.
Lets say you want to refer to cell A1. In Name Manager, create a Name, lets say YourNamedRange workbook scope, Reference =!$A$1 (Note the ! without a sheet reference).
When you add a formula to a sheet (eg =YourNamedRange) it will refer to cell A1 on the sheet containing the formula.
Applying it to your UDF, just use =PrevSheet(YourNamedRange)
Your UDF works (mostly) as is, but will fail if a different Workbook is active. To fix that, use
Function PrevSheet(RCell As Range)
Dim xIndex As Long
Application.Volatile
xIndex = RCell.Worksheet.Index
If xIndex > 1 Then
With RCell.Worksheet.Parent 'The workbook containing RCell
PrevSheet = .Worksheets(xIndex - 1).Range(RCell.Address)
End With
End If
End Function
There is also a WorksheetProperty called Previous that does much the same thing, so you can refactor as
Function PrevSheet(RCell As Range) As Variant
Application.Volatile
PrevSheet = RCell.Worksheet.Previous.Range(RCell.Address).Value
End Function

VBA coding to identify and clear data in a specific table

I am new to using VBA and would like to add coding to a button that will identify the size of a table called "QA_Activity" and clear all but the header row on clicking the button. I was hoping that this would be quite simple but am struggling as to how to identify a table that could be a different size each month. Many thanks in advance.
Tables are called ListObjects in VBA. A ListObject has a property called a .DataBodyRange that contains everything under the header. That has a .Clear method.
I generally use this syntax to clear the body of a ListObject:
Range("Table1").ListObject.DataBodyRange.Clear
The Range("Table1") bit allows me to find the ListObject even if I don't know what sheet it's on. This works because Tables are also Named Ranges that you can address by name. So you just say "Go to the Named Range called Table1, and get me the ListObject that lives there". Otherwise you would need to know in advance what sheet the ListObject is on, and use the following:
Worksheets("SomeSheet").Listobjects("Table1").DataBodyRange.Clear
...which works just fine until one day you move the Table to a different sheet, and forget to update your code.
Note that a table is not guaranteed to actually have a .DataBodyRange, because someone may have deleted all the rows under the header. For instance, take this Table:
How many rows does it have in the DataBodyRange?
? Range("Table1").ListObject.DataBodyRange.Rows.Count
3
Okay, now I'm going to delete those rows:
...leaving this:
How many rows in that DataBodyRange now?
? Range("Table1").ListObject.DataBodyRange.Rows.Count
Whoops...you can't reference a .DataBodyRange if it don't exist.
So to be safe, stick an On Error Resume Next before you try to reference a .DataBodyRange, and an On Error Goto 0 afterwards. Or something fancier.
First, create a named range. If required, you can make this dynamic. In this example the named range is Name "Data".
Then Trigger the Sub "Test" from the following VBA code.
Option Explicit
Sub ClearRange(ByVal rngCell As Range)
Dim rngRange As Range
Set rngRange = rngCell.CurrentRegion
rngRange.Range(rngRange.Parent.Cells(2, 1), rngRange.Parent.Cells(rngRange.Rows.Count, rngRange.Columns.Count)).ClearContents
End Sub
Sub test()
Dim rngCell As Range
Set rngCell = ActiveSheet.Range("Data").Cells(1, 1)
ClearRange rngCell
End Sub
This should clear the range except for the first row (headers).
Important: The header row and the first column of your range must be filled completely (no empty cells) for the above to work smoothly.

Excel VBA union deletes data from column

What I am doing is very simple - selecting a union of columns which contain numbers stored as text and converting them. Every time this runs, all even union numbered columns of data are getting cleared.
Union(Columns(19), Columns(22), Columns(25), Columns(28), Columns(31), Columns(34), Columns(37), Columns(40), Columns(43), Columns(46)).Select
With Selection
.Value = .Value
End With
I've looked though my entire code multiple times are cant figure why this is behaving so weird. any help is greatly appreciated.
The Value property of a discontiguous range only returns the first area of that range. When you then try and assign that value (array, in this case) back to a discontiguous range, you get strange results. For this particular case, every second column will get the value of the first cell in the first area.
You should loop through the areas in your range.
For each rArea in Selection.Areas
rarea.value2 = rarea.value2
Next rarea
Try to avoid using Select, and fully qualify your ranges. This makes things easier to diagnose and more robust...
Dim myRange As Range
With ThisWorkbook.Sheets("Sheet1")
Set myRange = Union(.Columns(19), .Columns(22), .Columns(25)) ' etc.
End With
Now if you're trying to convert text to numbers, you might be better off using the NumberFormat property as discussed here: What are .NumberFormat Options In Excel VBA?
Looping through range areas and number-formatting:
Dim area As Range
For Each area In myRange.Areas
area.NumberFormat = 0 ' for numbers, could still use area.Value = area.Value
Next area

Resources