multiple dims lastrow vba - excel

Im not too familiar with VBA, so the code below is mostly just copy and paste and research, just cant couldnt find a way to use Dim multiple times to be able to use it for different columns. Is there something I could add in front of "lastrow" to make it a different without getting the "compile error: Duplication declaration in current scope".
Dim lastrow As Long
lastrow = Worksheets("Sheet1").Range("A" & Rows.Count).End(xlUp).Row
Dim pointer As Integer
pointer = 1
Do Until pointer > lastrow - 1
Range("D1").Select
Sheet1.Range("D" & pointer).NumberFormat = "mm/dd/yyyy"
pointer = pointer + 1
Loop

You can remove the line with .Select in it, as it is not needed, and you can set the .NumberFormat of multiple cells within the loop if you want.
But there is an easier way, you can set the .NumberFormat property of an entire column with one line of code and no loop:
WorkSheets("Sheet1").Range("D:D").NumberFormat = "mm/dd/yyyy"
And for that matter, you can do multiple columns all at once too...
WorkSheets("Sheet1").Range("D:E,G:G,I:J").NumberFormat = "mm/dd/yyyy"

You can't dim a variable multiple times in one function or sub (hence the syntax error). There are some programming languages such as Java which has a notion of block-level scope in which such redeclarations are possible. VBA is not one of those languages.
Perhaps this is an XY problem and what you really want to do is to reinitialize the variable in each pass through an outer loop. That is nonproblematic, just lastrow = 0 whenever you are tempted to redeclare it.
That said, for this particular problem follow the recommendations of braX. In VBA, it is often possible to deal with ranges as a whole rather than looping cell by cell.

Related

VBA Error Run-time error 6 'Overflow', What is the problem?

I am a Programmer but never use VBA. I am taking over someone's old script and it keeps failing at a certain point with a Run-Time Error.
The Debugging report is here:
Please let me know if you need more code. I have tried to change currRow to Long, single, double, string none work. Below is a quick glimpse of the sheet that is failing. The top row is row one.
My guess is that this is missing an IsEmpty:
Do While Not IsEmpty(Cells(currRow, 20))
However, this loop is a very inefficient way to find the last row.
I believe something like this is what you want:
With ActiveWorkbook.Worksheets("Analysis")
Dim lastRow As Long
lastRow = .Cells(.Rows.Count, 20).End(xlUp).Row
.Range(lastRow + 1 & ":" & .Rows.Count).ClearContents
End With
Additionally:
Don't use Integer, use Long.
Avoid using Select
How to find the last used cell.

Object Required or Object variable or With Block errors

I am trying to use VBA to combine data from several different look up ranges for an SQL script writer. At this stage I am trying to identify whether the value I am looking up has an adjacent cell with a specific value. I have tried several iterations. My most recent is the following:
Dim r As String
With Worksheets(12).Range("q2:R80")
r = Cells(.Find(u(0, 1).Row, 18)).Value
End With
I have tried with and without the "With" statement as well as with and without "." before the methods and properties and with and with out the ".Value" and no matter what combination I use, I get an object error of some kind or another. I know I am missing something obvious, but Google has been of no help.
Your parentheses look off:
With Worksheets(12).Range("q2:R80")
r = Cells(.Find(u(0, 1).Row, 18)).Value
End With
seems like it should be:
With Worksheets(12).Range("q2:R80")
r = Cells(.Find(u(0, 1)).Row, 18).Value
End With
But this is still problematic, becauses it assumes the Find succeeded by chaining the .Row call.
Better practice is the following:
With Worksheets(12).Range("q2:R80")
Dim foundRng as Range
Set foundRng = .Find(u(0,1)) '<~ you really should specify the other parameters of Range.Find
If Not foundRng Is Nothing Then
r = Cells(foundRng.Row, 18).Value '<~ make sure to qualify the worksheet the Cells are on
End If
End With

VBA how to change a range variable using something like offset

I'd think that the following code should produce a diagonal of numbers, and I am wondering why this code doesn't work as intended:
Sub RangeExample()
Dim a As Range
Set a = Sheets(1).Range("a1")
a.Value = 0
Dim i As Integer
For i = 1 To 100
a = a.Offset(1, 1)
a.Value = i
Next i
End Sub
I understand there are many ways of producing a diagonal of numbers, I'm not asking how to do that.
What I'm asking is how I would change my range variable a to become a different range, and do that iteratively. It seems to me that as a.offset(1,1) returns a range object that's one over and one down, I should be able to reassign a as this new range, assign a value, and move on.
Your current issue is that you're missing a Set:
Set a = a.Offset(1, 1)
Note that you could also just use i and not reSet:
a.Offset(i, i).Value = i
Another option is to use Cells, e.g.
Sheets(1).Cells(i + 1, i + 1).Value = i
There's more than one way to skin a cat - pick whatever is easiest and most intuitive to future you.
Thanks for the answer, I didn't know set was required in this case. The specific answer I was looking for I have now found at:
What does the keyword Set actually do in VBA?
Specifically, the following answer by LeppyR64. "Set is used for setting object references, as opposed to assigning a value."
I didn't know that equality alone only impacted the value of the range object a. To actually change the range a was referencing, I needed set because a is supposed to refer to a new range object.
the issue has already been addressed by #BigBen
but you could avoid re-setting the range at every iteration by means of With...End With block
Option Explicit
Sub RangeExample()
Dim i As Long
With Sheets(1).Range("a1") ' reference topleftmost cell
.Value = 0 ' write referenced cell value
For i = 1 To 100
.Offset(i, i).Value = i 'write referenced cell current offset value
Next
End With
End Sub

Excel VBA Button - Fast way to change reference cell

Uh hello stackoverflow, I just started learning excel VBA for works and I find a problem that is I have to manually change the reference cell of a button manually for 500 buttons I wanted to make. For simplification sake:
Say in Column A I have several information normally hidden.
I put a button in each cell of Column B which will display the information in Column Ax (x being the cell number) to Cell Cx. Say:
Range("C1").Value = Range("A1").Value
The button I put in B1 would do the above, that is showing the value of C1 to be what is put in A1.
Now, I have 500 rows of data like this. Is it possible to make a dynamic buttons that knows the cell it is positioned in, and when moved/copy pasted to another cell, refer to its new location to dynamically change the reference cell in its code (Ax and Cx in that example)? So if I put the button in cel B67, the reference cell in the button code would change to C67 and A67 respectively.
[Before answering, here's my take on the things:]
I think the question you're trying to ask here is "how to find the last non-empty row".
The reason why I'm not flagging it as one is because, you may not be aware that you actually should be asking that question.
In general (and without meaning to sound condescending) you probably should study up on the programming basics first before asking questions like this here. Take some basic course somewhere (there are many) and only then begin experiment with some coding, because if you're missing coding fundamentals, then you'll never understand the bigger pictue behind it
What you're trying to describe here is a basic loop in programming language.
How does the loop work?
Let's pretend that we're a computer and we could also speak (in human language, not binary 1s and 0es).
I want to go through all the cells in a dynamic range
I need to know where does the dynamic range start and end (fetch me ending point)
I'll begin at starting point and end at ending point (duhh, silly humans should know that...)
For each and every cell in the range I'll do a certain action.
And that's it, fairly easy. Was a matter of seconds.
If we were trying to exactly represent what I described here:
Option Explicit ' < prevents you from typos, undeclared variables and so on...
Private Sub eachActiveCell()
Dim actionrange as Range
Dim lastrow as Long
lastrow = Sheets("Your Sheet Name").Cells(Rows.Count, "A").End(xlUp).Row
'finds last (active) row ^
Set actionrange = Sheets("Your Sheet Name").Range(Cells(1, "A"), Cells(lastrow, "A"))
' this sets our range to (A1:A <lastrow>) ^
Dim cell as Range
For each cell in actionrange
cell.Offset(0, 2) = cell.Value2 ' utilizes offset, A1 offset by 2 columns = C1
Next cell
End Sub
Other alternative, as it may be easier to comprehend with rows, rather than Ranges.
Option Explicit
Private Sub foriinA()
Dim ws as WorkSheet: Set ws = Sheets("Your Sheet Name")
Dim lastrow As Long
lastrow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
Dim i As Long
For i = 1 To lastrow
ws.Cells(i, "C") = ws.Cells(i, "A")
Next i
End Sub

Trying to Remove Duplicates based on first column

I am currently trying to remove rows from column A to column V based on duplicates found in column A.
my current formula is:
Workbooks(TgtWB).ActiveSheet.Range("A15:V500").RemoveDuplicates _
Columns:=Array(1), Header:=xlYes
My header is located on row 15.
the error i am getting is
Application-defined or object-defined error
I have tried switching ActiveSheet with worksheet("xxx") but still doesn't seem to work either. i'm not sure what i'm doing wrong here.
Try (note worksheetS, not worksheet),
Workbooks(TgtWB).worksheetS("xxx").Range("A15:V500").RemoveDuplicates Columns:=1, Header:=xlYes
'or,
ActiveSheet.Range("A15:V500").RemoveDuplicates Columns:=1, Header:=xlYes
If TgtWB is open, it may or may not contain the ActiveSheet. Each open workbook does not have an ActiveSheet. There is only one ActiveSheet for the application instance. ActiveSheet is not a property of the Workbooks collection.
Using built in functionality is great, unless you're a beginner like myself and the .Applications and .Worksheets get overwhelming and confusing. For a small data set, such as columns A through V (depending obviously on how many rows you have), a loop and if-statement not only can work well, but can be good practice as well! Something like this may work well:
Dim CurrentValue, LastValue As Variant
LastValue = ""
For I = 1 To 500
CurrentValue = Sheets("Sheet 1").Range("A" & i).Value
If CurrentValue = LastValue Then
Sheets("Sheet 1").Range("A" & i & ":V" & i).Clear Contents
Else
LastValue = CurrentValue
End If
Next i
This will loop through every row, ask if the current value in the cell is the same as the one previously observed (except the first one, the first one will automatically be saved by nature), and if it has been, it will clear the contents of the row. If it's not the same, it will assign it to the new variable and begin looking for new ones.
There are two drawbacks with this method that can be solved by simply adapting the code to your needs:
Non-Sequential Items: If the values that are duplicates are not sequential, the code won't kick them out. At that point I recommend using an application code or a dictionary. Dictionaries are infinitely useful for storing unique data entries and skipping duplicates.
Deleting Rows: When you delete rows in a loop it messes up your loop, throwing off the order of your incrementer. The best way to combat this is by first clearing the columns then having your code loop for empty rows and delete them outside of your loop.
This is very basic but something I've found greatly helpful as a beginner and hopefully other beginners and yourself can learn something from it.
Happy Coding!

Resources