Variable not defined error upon execution - excel

can someone explain why I get a variable not defined error on this private sub?
Private Sub CommandButton4_Click()
'Autocomplete Button
Dim w As Long, lastRow As Long
For w = 2 To lastRow
'If existing data = entered data
If sh.Cells(w, 2).Value = Me.TextBox1.Value Then
'fill textbox with associated existing data from same row
Me.TextBox2.Value = sh.Cells(w, 3).Value
'save value of i in invisible textbox because no better solution came to mind yet
Me.TextBox8.Value = w
Exit Sub
End If
Next w
End Sub

The error occurs because you used a variable but did not declare it before. This variable looks like to be sh. So if sh is not a global variable then you need to delare it and set it to your desired worksheet before using the variable:
Dim sh As Worksheet
Set sh = ThisWorkbook.Worksheets("YourSheetName")
Also note that lastRow has no value and therefore is 0 before you use it you need to set a value for this variable.
Otherwise For w = 2 To lastRow is just For w = 2 To 0 and therefore will never run.

Related

Still Run time error 1004 'Unable to get the VLookup property of the WorksheetFunction class

I got this error and I tried to fixed with many solution, but I don't know why this error is happening. Could you help me to fix this problem? In this code I have twice used VLookup function same source, different only Worksheet name and column. Another one can compile this code and don't have any error.
I'm doing, VLookup item on column B of worksheet "ImportData2" match with column A of worksheet "Noallocate" if match show result of VLookup at column Q of worksheet "ImportData2"
get this error
Source code:
'Vlook up function no import
Dim Vrow1 As Long
Dim myLookupValue1 As String
Dim myFirstColumn1 As Long
Dim myLastColumn1 As Long
Dim myColumnIndex1 As Long
Dim myFirstRow1 As Long
Dim myLastRow1 As Long
Dim myVLookupResult1 As String
Dim myTableArray1 As Range
For Vrow1 = 2 To 99999
myLookupValue1 = Workbooks("ExpenseData.xlsm").Worksheets("ImportData2").Range("B" & Vrow).Value
myFirstColumn1 = 1
myLastColumn1 = 2
myColumnIndex1 = 2
myFirstRow1 = 2
myLastRow1 = Workbooks("ExpenseData.xlsm").Worksheets("Noallocate").Range("b1").End(xlDown).Row
With Workbooks("ExpenseData.xlsm").Worksheets("Noallocate")
Set myTableArray1 = .Range(.Cells(myFirstRow1, myFirstColumn1), .Cells(myLastRow1, myLastColumn1))
End With
myVLookupResult1 = WorksheetFunction.VLookup(myLookupValue1, myTableArray1, myColumnIndex1, False) 'xxx
Workbooks("ExpenseData.xlsm").Worksheets("ImportData").Range("Q" & Vrow).Value = myVLookupResult1 'xxx
Next 'end function no import
Try the next code, please. It would be a good habit to have 'Option Explicit' on top of your module. This will oblige you to declare all variables. It looks, your code iterates using Vrow1 but inside the loop you used Vrow... I discovered it only after trying to make your code a little friendlier. It is not good to use big variables name instead of 1, 2. This can only make the code more difficult to be understood by looking at it. As short it would be, as easy to be understood and debugged:
Sub testVlookup()
Dim Wb As Workbook, Vrow1 As Long, lastRDat As Long, wsNoall As Worksheet
Dim wsImpD2 As Worksheet, myLookupValue1 As String, myLastRow1 As Long
Dim myVLookupResult1 As String, myTableArray1 As Range
Set Wb = Workbooks("ExpenseDataMcframe.xlsm")
Set wsNoall = Wb.Worksheets("Noallocate")
Set wsImpD2 = Wb.Worksheets("ImportData2")
myLastRow1 = wsNoall.Range("b" & Rows.count).End(xlUp).Row
lastRDat = wsImpD2.Range("B" & Rows.count).End(xlUp).Row
For Vrow1 = 2 To lastRDat
myLookupValue1 = wsImpD2.Range("B" & Vrow1).value
Set myTableArray1 = wsNoall.Range(wsNoall.Cells(2, 1), wsNoall.Cells(myLastRow1, 2))
On Error Resume Next 'for the case when lookup_value is not found
myVLookupResult1 = WorksheetFunction.VLookup(myLookupValue1, myTableArray1, 2, False) 'xxx
If Err.Number <> 0 Then
Err.Clear: On Error GoTo 0
Wb.Worksheets("ImportData").Range("Q" & Vrow1).value = "Not a mach"
Else
Wb.Worksheets("ImportData").Range("Q" & Vrow1).value = myVLookupResult1 'xxx
End If
On Error GoTo 0
Next
End Sub
When the lookup_value is not found, the code will return (on Q:Q column) "Not a match" and you must check the specific code/whatever it is...

Excel VBA Run time Error 424: Object Required

I am totally new in VBA and coding in general, I'm trying to get data from cells from the same workbook if the condition is met to paste in another book.
I am getting this error when trying to get values entered in excel cells:
Run Time Error '424' object required
When I'm pressing the debug button it takes to the first line and highlights it. I am not able to recognize why it is happening? Also when in watch window it shows a=0.
The code is
Sub copycells()
a = ThisWorkbook.Worksheets("Sale").Cells(Row.Count, 2).End(xlUp).Row
For i = 2 To a
If Worksheets("Sale").Cells(i, 6).Value = "Parmesh" Then
Worksheets("Sale").Row(i).copy
Workbooks("Source.xlsx").Worksheets("Billdetails").Activate
b = Workbooks("Source.xlsx").Worksheets("Billdetails").Cells(Row.Count, 2).End(xlUp).Row
Workbooks("Source.xlsx").Worksheets("Billdetails").Cells(b + 1, 1).Select
ActivateSheet.Paste
Worksheets("Sale").Activate
End If
Next
Application.CutCopyMode = False
Workbooks("Purchase.xlsx").Worksheets("Sale").Cells(1, 1).Select
End Sub
Option Explicit: Your Friend
That should teach you to always use Option Explicit. If you had been using it the following might have happened (Compile error: Variable not defined):
After OK:
you see that something is wrong with Row.
After changing to Rows another Compile error: Variable not defined. After OK:
you see that something is wrong with a =.
After adding Dim a As Long another Compile error: Variable not defined. After OK:
you see that something is wrong with i.
After adding Dim i As Long another Compile error: Variable not defined. After OK:
You see something is wrong with Row again.
After changing to Rows another Compile error: Variable not defined. After OK:
you see that something is wrong with b =.
After adding Dim b As Long another Compile error: Variable not defined. After OK:
you see that something is wrong with ActivateSheet.
After changing to ActiveSheet finally a Run-time error:
and after Debug:
Row looks suspicious again.
After changing to Rows another Run-time error:
and after Debug:
you see that something is wrong with ActiveSheet.Paste, especially Paste.
After changing to ActiveSheet.PasteSpecial another Run-time error:
and after Debug:
you see something is wrong with Worksheets("Sale").Activate.
Since Source.xlsx is active you consider changing to Workbooks("Purchase.xlsx").Worksheets("Sale").Activate and everything's finally OK. Or is it?
The Code
Option Explicit
Sub copycells()
Dim a As Long
Dim b As Long
Dim i As Long
With ThisWorkbook.Worksheets("Sale")
a = .Cells(.Rows.Count, 2).End(xlUp).Row
For i = 2 To a
If .Cells(i, 6).Value = "Parmesh" Then
.Rows(i).Copy
With Workbooks("Source.xlsx").Worksheets("Billdetails")
b = .Cells(.Rows.Count, 2).End(xlUp).Row
.Cells(b + 1, 1).PasteSpecial
End With
End If
Next
' If Purchase.xlsx and ThisWorkbook are the same then use the following:
'.Cells(1).Select
End With
Application.CutCopyMode = False
' If Purchase.xlsx and ThisWorkbook are not the same then use the following:
'Workbooks("Purchase.xlsx").Worksheets("Sale").Cells(1, 1).Select
End Sub
' Assuming that you need only values and that "Thisworkbook" is "Purchase.xlsx"
Sub copyCellsValues()
Const SourceBook As String = "Source.xlsx"
Const SourceSheet As String = "Billdetails"
Const MainSheet As String = "Sale"
Const MainColumn As Long = 6
Const Criteria As String = "Parmesh"
Dim Sale As Worksheet
Dim Bill As Worksheet
Dim a As Long
Dim b As Long
Dim i As Long
Set Sale = ThisWorkbook.Worksheets(MainSheet)
Set Bill = Workbooks(SourceBook).Worksheets(SourceSheet)
a = Sale.Cells(Sale.Rows.Count, 2).End(xlUp).Row
b = Bill.Cells(Bill.Rows.Count, 2).End(xlUp).Row + 1
For i = 2 To a
If Sale.Cells(i, MainColumn).Value = Criteria Then
Bill.Rows(b).Value = Sale.Rows(i).Value
b = b + 1
End If
Next
End Sub
First of all, it seems you need to declare missed variable:
Sub copycells()
Dim a as Integer
Dim b as Integer
a = ThisWorkbook.Worksheets("Sale").Cells(Row.Count, 2).End(xlUp).Row
For i = 2 To a
If Worksheets("Sale").Cells(i, 6).Value = "Parmesh" Then
Worksheets("Sale").Row(i).copy
Workbooks("Source.xlsx").Worksheets("Billdetails").Activate
b = Workbooks("Source.xlsx").Worksheets("Billdetails").Cells(Row.Count, 2).End(xlUp).Row
Workbooks("Source.xlsx").Worksheets("Billdetails").Cells(b + 1, 1).Select
ActivateSheet.Paste
Worksheets("Sale").Activate
End If
Next
Application.CutCopyMode = False
Workbooks("Purchase.xlsx").Worksheets("Sale").Cells(1, 1).Select
End Sub
Also, you may try to use the Set operator.
Anyway, it is not clear what property or method gives an error. So, I'd recommend breaking the chain of property and method calls:
a = Workbooks("Purchase.xlsx").Worksheets("Sale").Cells(Rows.Count, 2).End(xlUp).Row
Just declare separate lines of code where a single property or method will take its place. For example:
Dim workbk as Excel.Workbook
Dim worksht as Excel.Worksheet
Set workbk = Workbooks("Purchase.xlsx")
Set worksht = workbk.Worksheets("Sale")
Following that way, you will be able to find the problematic call.

Is there a way to reassign a Range variable to a different range?

I am very new to VBA, having started programming it yesterday. I am writing a data processing program which requires keeping track of two cells, one on each spreadsheet. The code which reproduces the errors I am experiencing is below. When I call the sub moveCell() in sub Processor(), nothing happens to DIRow and DIColumn, and the code spits out error 1004 at the line indicated. I have tried using DICell = DICell.Offset(), but it returns the same error.
How can I redefine a Range variable to be a different cell?
'<<Main Processor Code>>'
Sub Processor()
Dim PDRow As Integer
Dim PDColumn As Integer
Dim DIRow As Integer
Dim DIColumn As Integer
PDRow = 1
PDColumn = 1
DIRow = 1
DIColumn = 1
Dim PDCell As Range
Dim DICell As Range
Set PDCell = Worksheets("Processed Data").Cells(PDRow, PDColumn)
Set DICell = Worksheets("Data Input").Cells(DIRow, DIColumn)
Call moveCell(2, 0, "Data Input")
End Sub
'<<Function which moves the cell which defines the range>>'
Sub moveCell(r As Integer, c As Integer, sheet As String)
If sheet = "Processed Data" Then
PDRow = PDRow + r
PDColumn = PDColumn + c
Set PDCell = Worksheets("Data Input").Cells(PDRow, PDColumn)
ElseIf sheet = "Data Input" Then
DIRow = DIRow + r '<<<<<<This line does nothing to DIRow's value
DIColumn = DIColumn + c
Set DICell = Worksheets("Data Input").Cells(DIRow, DIColumn) '<<<<<<This line causes error 1004
End If
End Sub
As far as I can tell, you could instead use a quick Function instead. There doesn't seem to be any difference in your If statement results in the moveCell() function, except which worksheet you're using.
We can make this simpler by referring to the Range you're passing to moveCell.
Option Explicit ' forces you to declare all variables
Sub something()
Dim PDCell As Range
Set PDCell = Worksheets("Processed Data").Cells(1, 1)
Dim DICell As Range
Set DICell = Worksheets("Data Input").Cells(1, 1)
PDCell.Select ' can remove
Set PDCell = moveCell(2, 0, PDCell, PDCell.Worksheet.Name)
PDCell.Select ' can remove
Worksheets(DICell.Worksheet.Name).Activate ' can remove
DICell.Select ' can remove
Set DICell = moveCell(5, 0, DICell, DICell.Worksheet.Name)
DICell.Select ' can remove
End Sub
Function moveCell(rowsToMove As Long, colsToMove As Long, cel As Range, ws As String) As Range
Set moveCell = Worksheets(ws).Cells(cel.Row + rowsToMove, cel.Column + colsToMove)
End Function
I've included some rows you don't need (which I've marked with a comment afterwards), but that will show you how the routine works. You can step through with F8 to help see it step-by-step.
Edit: Although, you don't need a separate function at all. Just use OFFSET().
Set PDCell = ...whatever originally
Set PDCell = PDCell.Offset([rows],[cols])

The temp line shows type mismatch error

Sub assign_sr_no()
For Each sh In ThisWorkbook.Sheets
If sh.Name = "master" Then GoTo gogo
If sh.ProtectContents = False Then GoTo gogo
Dim srno As String
Dim temp As Integer
temp = CInt(Right(Sheets("master").Range("A65536").End(xlUp).Text, 4))
srno = "VE17" & "_" & Format(temp + 1, "0000")
sh.Unprotect "VALUE"
sh.Cells.Validation.Delete
sh.Range("L1").Value = srno
sh.Hyperlinks.Add Anchor:=sh.Range("A1"), SubAddress:="master!A1", Address:="", TextToDisplay:="Faridabad Plant"
Call copy_from_ve(srno)
gogo:
Next
End Sub
This piece of code is used to assign serial numbers to the sheet and then there is another code which copies data from the sheet to the master sheet.
The temp line shows
error 13 i.e. type mismatch error.
The whole excel table is empty i have this 25 columns [...]
You can't convert an empty string into an Integer using the CInt function. This code reproduces the error:
Debug.Print CInt("")
You could use the Val function to get yourself a Double that you can convert to an Integer if you're absolutely certain you'll never ever need a value greater than 32,767. Otherwise, use a Long.
temp = Val(Right(Sheets("master").Range("A65536").End(xlUp).Text, 4))
You should really break up that statement though, and pull it out of the loop body if it's constant at every iteration.
Also Excel >2003 has way more than 65K possible rows on a worksheet; consider using .Range("A" & [ActiveSheet.]Rows.Count) (or pull the Sheets("master") into its own With block variable, or better, use the sheet's CodeName:
With MasterSheet ' assuming (Name) property was set to "MasterSheet"
Dim lastValue As String
lastValue = .Range("A" & .Rows.Count).End(xlUp).Text
Dim temp As Long
temp = Val(Right(lastValue, 4)
Dim sh As Worksheet
For Each sh In ThisWorkbook.Worksheets
If sh.Name <> .Name Then ' no need for GoTo jumping here
'...
End If
Next
End With

How to target a specific shape in excel sheet

Program: Excel 2016.
I have a sheet with a lot of shapes. Each of them has its own specific name and most of them are label. I want to change their caption property, but i can't find a way but calling them one by one like this:
LblLabel_1.Caption = ...
LblLabel_2.Caption = ...
LblLabel_3.Caption = ...
Instead i was looking for something like this:
For BytCounter01 = 1 to 255
Shapes("LblLabel_" & BytCounter01).Caption = ...
Next
This one will result in error 438, basically saying Caption is not avaiable for this object. It still target the object, since this code:
Debug.print Shapes("LblLabel_" & BytCounter01).Name
will return me its name.
Looking for a solution:
-i've tried Controls("LblLabel_" & BytCounter01) instead of Shapes("LblLabel_" & BytCounter01) but it won't work since Controls is only for userforms, not for sheets;
-i've tried Shapes("LblLabel_" & BytCounter01).TextFrame.Characters.Text but it returns error 438 again;
-since the label is a part of a group, i've tried both
Shapes("ShpGroupOfShapes01").GroupItems(ShpShapeIndex).Caption
and
Shapes("ShpGroupOfShapes01").GroupItems(ShpShapeIndex).TextFrame.Characters.Text
but got 438 again.
Is there really no way to easily target a specific label on a sheet and change his caption?
Thank you.
EDIT: thanks to Excelosaurus, the problem is solved. Since my labels are ActiveX Controls i have to use something like this:
For BytCounter01 = 1 to 255
Shapes("LblLabel_" & BytCounter01)OLEFormat.Object.Object.Capti‌​on = ...
Next
You can check his response and comments for more details. Thanks again Excelosaurus!
To change the textual content of a shape, use .TextFrame2.TextRange.Text as shown below:
shtShapes.Shapes(sShapeName).TextFrame2.TextRange.Text = sShapeCaption
where shtShapes is the name of your worksheet's object as seen from the Visual Basic Editor in the Project Explorer,
sShapeName is a string variable containing the name of the target shape, and
sShapeCaptionis a string variable containing the desired caption.
A code example follows. I've thrown in a function to check for a shape's existence on a worksheet, by name.
Option Explicit
Public Sub SetLabelCaptions()
Dim bCounter As Byte
Dim sShapeName As String
Dim sShapeCaption As String
For bCounter = 1 To 255
sShapeName = "LblLabel_" & CStr(bCounter)
If ShapeExists(shtMyShapes, sShapeName) Then
sShapeCaption = "Hello World " & CStr(bCounter)
shtMyShapes.Shapes(sShapeName).TextFrame2.TextRange.Text = sShapeCaption
Else
Exit For
End If
Next
End Sub
Public Function ShapeExists(ByVal pshtHost As Excel.Worksheet, ByVal psShapeName As String) As Boolean
Dim boolResult As Boolean
Dim shpTest As Excel.Shape
On Error Resume Next
Set shpTest = pshtHost.Shapes(psShapeName)
boolResult = (Not shpTest Is Nothing)
Set shpTest = Nothing
ShapeExists = boolResult
End Function
The result should look like this:
You can't assign a Caption to a Shape. (Shapes don't have Captions). One approach is to loop over the Shapes and build a little table to tell you what to loop over next:
Sub WhatDoIHave()
Dim kolumn As String, s As Shape
Dim i As Long, r As Range
kolumn = "Z"
i = 1
For Each s In ActiveSheet.Shapes
Set r = Cells(i, kolumn)
r.Value = i
r.Offset(, 1).Value = s.Name
r.Offset(, 2).Value = s.Type
r.Offset(, 3).Value = s.TopLeftCell.Address(0, 0)
i = i + 1
Next s
End Sub
Which for my sample produced:
Seeing that I have both Forms and ActiveX (OLE) Controls, I know what to loop over next. I then refer to the Control by number and assign a Caption if appropriate.

Resources