To my astonishment, I realized that I could not set a range at some point of my code. And I've found nowhere any mention of this issue.
So I declared (with dim) a Range variable.
And then I do Set Myvar = Worksheets("blabla").Range("A1:C3")
And Excel throw me an error code 9, out of range...
When I put the same line at the top of my code, it works (where I have my other sets).
Is that a known spec of VBA or is there something wrong for me ?
edit:
Apparently, the problem wasn't "set", but the fact that I can select a range only when the workbook is activated.
My code:
Transform_file.Worksheets("general balance").Range(Cells(startline, 1), Cells(LastCellNumber, 1)).Value = "cool"
Works only if I have Transform_file.activate before
Hence the issue
of my question wasn't Set, which can apparently be used anywhere.
I think the problem is that you are not aware how VBA uses some common defaults and assumptions. When you use:
Worksheets("blabla")
Excel assumes you mean this:
ActiveWorkbook.Worksheets("blabla")
I fact it assumes even more:
Application.ActiveWorkbook.Worksheets("blabla")
The best way to avoid these kinds of issues is to be explicit in your code by creating a workbook object when you open the workbook. Like so:
Dim wkb As Workbook
Set wkb = Workbooks.Open("blah.xls")
wkb.Worksheets("blabla")
Or if you your code refers to a worksheet that is in the same workbook as your code then you could use:
ThisWorkbook.Worksheets("blabla")
These assumptions also work for for properties of objects which is why the language has the SET command. So example when you code:
Range("A1")
What Excel will acually return is:
Range("A1").Value
This is because Value is the default property of a Range Object. The language is built this way I assume to save coding - most of the time you would wnat the Value of the range. The problem is when you want to assign the object to a variable and not it's default property which when you need to use SET. SET just says return the entire object.
Related
I am attempting to copy different images to different worksheets of my Workbook using the following code below. I am changing the Target Worksheet Dynamically in a different sub, with a String Variable in the Global Declarations section. I can see the variable being passed to the sub and in fact it works the first pass through the code, but when I attempt to change the "TargetSheetIni" variable to a new sheet, it continues to use the first original sheet as it loops through.
Can you not change a target sheet after using the Set keyword? Should I refer to the sheet directly instead?
Sub Test1()
Dim TargetWS, SourceWS As Worksheet
Set TargetWS = Worksheets(TargetSheetIni)
Set SourceWS = Worksheets("Images")
DoEvents
SourceWS.Shapes(CurrentImageId).Copy
DoEvents
TargetWS.Paste Range(ColumnLetter2 & RwCnter)
DoEvents
End Sub
I think I may have figured it out. As far as I can tell the issue may be that I used the Copy Sheet Functionality in Excel when I originally created the target sheets. And even though I renamed the sheets both on the tab below and in the project editor... for some reason VBA kept targeting only the original sheet
I proved this by changing my code around to explicitly call the sheet I wanted to target like so:
ActiveWorkbook.Worksheets("Sheet2").Paste Range("I2")
And even doing that it would target sheet 1 for the paste command instead of the expected sheet 2. I deleted the three copy sheets and created a new one from scratch and re-executed code and now it targets sheet 2 as expected.
I found this article that sort of explains it I guess...
https://www.spreadsheetsmadeeasy.com/7-common-vba-mistakes-to-avoid/
Ok my last answer may have not been correct. It appears as though for some reason inserting an ws.activate caused my code to start workin.g
Very frustrating fix. as I have always heard to avoid using that.
So there are a few ways to set a worksheet in Excel.
set WS = Sheets("Name Here!")
set WS = WB.Sheets("Name Here!")
set WS = shNameOfTheSheetObject
However, there doesn't seem to be a way to do:
set WS = WB.shNameOfTheSheetObject
I'd like to know how, if it's possible, I can get this type of reference to work. I like being very, very explicit with my code (Perhaps too much so), and it'd be useful to know if I have multiple workbooks open that I'm handling.
I think there is a slight confusion on how the access via the code name works. When you get a worksheet via ThisWorkbook.Worksheets("SheetName") you query a collection on the workbook; when you use the code name, you get the corresponding component of the VBA project containing your project, which implements the Worksheet interface.
Both are the same object, but the resolution of the identifier takes a different path: a workbook does not know about the VBA components. Consequently, as #Comintern mentioned in the comments, you can only use the project name of the containing VBA project as further qualifier. That name is whatever you set it to via the project properties dialog. If you do not change it, it will always be VBAProject in Excel, which is not very helpful.
I have a dataset with is quite simple. When I add data at the end of it, I want to automatically get that in my chartsheet.
For example:
At this moment, the chartsheet exists with a Datasource "A1:Q10". After I enter some values within the sheet where the Datascource is, it should change to A1:R10.
But it doens't work. Here the code which ends up in
"Application or object-defined error"
Sheets("_Chartsheet-sheet").Select
Activesheet.Chartobjects(1).Activate
ActiveChart.SetSourceDate Source:=Range("A10:" & ActualLetter & "10")
As ashleedawg noted, SetSourceDate isn't a member of the Chart class - using Option Explicit and the VBE's IntelliSense & auto-complete will help prevent these. Writing it off as a typo, there's another problem with the code...
Source:=Range("A10:" & ActualLetter & "10")
Range being unqualified, if that code is written in a standard code module, it implicitly refers to whatever the ActiveSheet is - in this case...
Sheets("_Chartsheet-sheet").Select
...a chart sheet, which isn't a Worksheet and, as such, doesn't have a Range property.
An unqualified Range call, made explicit, reads as follows:
[_Global].Range("address")
The solution is to properly qualify that Range call with the Worksheet object instance you mean to work with - assuming Sheet1:
Source:=Sheet1.Range("address")
That Sheet1 is a global-scope Worksheet object that you get for free, given that your worksheet exists at compile-time. Select the worksheet under "Microsoft Excel Objects" in the VBE's Project Explorer, then look at its properties (F4): you'll notice it has a Name property with a value that corresponds to its "tab name" (the name you'd use to fetch the worksheet by name), but it also has a (Name) property, with a value that corresponds to its "code name" - that's the identifier VBA uses to generate the free global-scope object variable you can (and should) use anywhere in your code whenever you need to refer to that worksheet.
Fetching that object from the Sheets or Worksheets collection by name, puts your code at risk: unless workbook structure is protected, the user can change that "tab name" at any time, and that will break every Worksheets("name") call in your code.
If the code is written in a worksheet's code-behind, then the unqualified Range call is implicitly referring to that worksheet. In that case, explicitly qualifying Range with Me would make the code more... explicit about its intent.
Lastly, .Select and .Activate aren't needed here. Avoid Select and Activate, it's macro-recorder code that's as frail as code gets. Instead, work the object references - here I'm assuming that the code is written in the source sheet's code-behind, hence the Me qualifier in front of Range:
Dim chartSheet As Chart
Set chartSheet = ThisWorkbook.Sheets("_Chartsheet-sheet")
chartSheet.SetSourceData Source:=Me.Range("A10:" & ActualLetter & "10")
I've been trying to use vlookup in VBA and it's being quite annoying.
ActiveCell.Value = Application.WorksheetFunction.VLookup(Cells(currentrow, 12), currwor.Worksheets("Sheet1").Range("R4C3:R160C10"), 6, False)
is the code
The main elements I've used are
currwor which has been set to reference another workbook and I'm looking to use vlookup on the range in there.
However it keeps kicking up an error saying subscript out of range.
I suspect currwor is the guilty party in this
Set currwor = ActiveWorkbook (then the workbook in which the above is executed is opened, and that is assigned a workbook name as well.)
I can't use a specific range because I'm trying to perform the vlookup on each cell in a range, and that range changes everytime, and the currwor is to be executed on a particular document I get but the name may vary (format however remains the same.)
Any suggestions on it?
edit: One error is that it's not supposed to be sheet1 but 'Stock Report by Product'. However it's still kicking up the subscript out of range error.
by using Set currwor = ActiveWorkbook
you assign currently active workbook to currwor however you mentioned prior to that it should be a different workbook? meaning you should have a line Set currworb = Workbooks("desired workbook name")?
Yes - Idiotic mistake. As pointed out the sheet name was incorrect and the problem was that in execution I skipped the bit where the worksheet was assigned to currwor.
Idiotic enough that I should consider deleting this post off here.
I'm pounding my head against the wall with this. I've been writing the full workbooks().sheets() references. Looking for a shorter way to do it I found some stackoverflow posts and answers that seem so simple but when I try it... it doesn't work.
I don't need to open the workbook I want to reference since I found a way to code it to open automatically when the main workbook opens... and save and close when the main closes.
I get a "Compile error: sub or function not defined" at the Set wb = Workbooks() line.
I followed as closely the answer to this question Referencing Workbook and Worksheet by Variables
Is there a special place to define an object variable or may it be done in any sub or function when needed. Also Is there a place I can define it where the whole project sees it so I only have to define it once. If so I'll define them all in that location and always use the shorthand references.
Public Sub VTest()
Dim WbStats As Workbook
Dim WSPO1sts As Worksheet
Set WbStats = Worksbooks("Stats.xlsx") 'this line spawns the compile error I mentioned.
Set WSPO1sts = WbStats.Sheets("PO1sts")
Note that if your code is in a workbook you can reference the workbook by using ActiveWorkbook
See here which will explain more about declaring (ie define) variables and their scope.
This site has a lot of information that you will find useful
eg
http://www.cpearson.com/Excel/DeclaringVariables.aspx
Harvey