I'm pretty new to VBA and I'm trying to hide some columns in workbooks.
I have to do it in VBA because the workbook is an Analysis for Office workbook, so I have to hide some columns that the final users don't have to see.
My problem is that I can't point to a specific letter of the columns, because, since the workbook is modifiable like a pivot with other dimensions in respect of the default ones with which it opens, if I point to a specific column in the code, it won't be the same when an user add new dimensions. So I have to find the column with its name ad hide it.
So for now I tried this:
Sub Hide_Columns()
'Dim Sourcecell As Range
Dim wb As Workbook
Dim ws As Worksheet
'Set Sourcecell = Nothing
'Set Sourcecell = ThisSheet.Range("SapCrosstab1").Find("Colonna di calcolo", LookIn:=xlFormulas)
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Demand Planning")
wb.Sheets("Demand Planning").Range("Colonna di calcolo").EntireColumn.Hidden = True
End Sub
The problem here is that I'm having the
"Run-time error 1004: Application-defined or object-defined error"
and I don't know how to fix it.
I commented that 3 lines because I'm not so sure they could help.
Your current attempt fails because Range("Colonna di calcolo") will not search for a column with that header. Instead, it want to access a Named Range with that name, and if you don't define this, it will throw exactly this error 1004.
I think your attempt with SourceCell was not bad - issue a Find command and hide the EntireColumn of the found cell. Your mistake was that there is no object ThisSheet. There are objects ThisWorkbook which refers to the entire workbook where the code is stored, or ActiveWorkbook which is the Workbook that is currently shown (not necessarily the workbook where the macro is stored).
You can solve your issue either by defining a Named Range for the column - in that case your code should work.
Or change the code to something like
Dim ws as Worksheet
Set ws = ThisWorkbook.Sheets("Demand Planning")
Dim Sourcecell as Range
Set Sourcecell = ws.Range("1:1").Find("Colonna di calcolo", LookIn:=xlFormulas)
If Not Sourcecell Is Nothing Then
Sourcecell.EntireColumn.Hidden = True
End If
Related
I am struggling with proper syntax for setting variables as ranges...
Specifically, I'm testing a function I want to use in an app that creates new profiles and store the data, I will store that data on a hidden sheet, so they can be recalled at run time.
I'm currently construction a userform in order to create a new profile, the profile data needs to be stored to the first free column on the hidden sheet.
(where I will have to create a dynamic namedRange, so that i can use that range to save the associated data, and update the listbox in the userform)
Right now, I'm stumped by this:
Sub TestFindLastFunctions()
Dim wb As Workbook
Set wb = ThisWorkbook
'wb.activate 'shouldn't be neccesary
Dim ws As Worksheet
Set ws = sh_02CRepStorage
'ws.activate 'shoudn't be neccesary
Dim trgtCol As Long
trgtCol = LastColInSheet(ws) + 2
Debug.Print trgtCol ' so far so good
'Cells(1, trgtCol).Select 'another debug check - only works if sheet activated
Dim trgtCell As Range
Set trgtCell = ws.Cells(1, trgtCol) '<------- problem line
Debug.Print trgtCell '<----- prints "" to the immediate window.
End Sub
The LastColInSheet function is copied form Ron de bruin's page: https://www.rondebruin.nl/win/s9/win005.htm it simply returns a column number, in this case: 4.(One problem with it is if the sheet is empty, it returns an error, wondering if this can be fixed with an if statement in the function.)
I've tried many iterations of the problem line, some work but only if the storage sheet is activated, and give an error if not activate or selected, as the sheet will be hidden, I need this to work without activating the sheet, (although I could switch off screen activation?).
But I understand that it is best practice to avoid extraneous selects and activates, how can I just point directly to what I want and save that range into a variable?
It just doesn't seem like it should be so difficult, I must be missing something obvious.
It also seems like it shouldn't need so many lines of code to do something so simple.
I tried some more iterations of the "problem line" after some more searching...
-The real problem was with the debug.print line
Sub TestFindLastFunctions()
Dim wb As Workbook
Set wb = ThisWorkbook
'wb.activate 'shouldn't be neccesary
Dim ws As Worksheet
Set ws = sh_02CRepStorage
'ws.activate 'shoudn't be neccesary
Dim trgtCol As Long
trgtCol = LastColInSheet(ws) + 2
Debug.Print trgtCol ' so far so good
'Cells(1, trgtCol).Select 'debug Only works if already on sheet
Dim trgtCell As Range
'Set trgtCell = ws.Range _
(ws.Cells(1, trgtCol), ws.Cells(1, trgtCol))
' unnecessarily complex, but correct if using .range?
'but works if insisting on range
Set trgtCell = ws.Cells(1, trgtCol) 'back to original
Debug.Print trgtCell.Address '<---problem was here?
End Sub
(Sorry in advance for my poor English: not first Language :) )
I am writing a VBA Excel 2003 routine that runs through 50+ worksheets in a file, copies the worksheets (just as a temp copy) one by one and then performs actions on them before removing these temporary copies and returning the result of it's calculations on the worksheets content.
To be more precise: the code is called from an external file with a single (hidden) worksheet inside. When I open the file it runs a code to create a new toolbar in Excel, when I press a button on the toolbar, the code I have described above runs.
I know that not saving a file and performing many and many copies triggers this error, but now it is triggering at the first attempt (I have closed and reopened everything multiple times to be sure I am not keeping the not saved situation with me).
This is the code triggering the problem, I am sorry for poor formatting:
ActiveWorkbook.Worksheets("NAME OF THE FIRST WORKSHEET I WANT TO COPY").Copy ThisWorkbook.Worksheets("HiddenSheet")
Disclamer: the name of the worksheet is found by a For..Next cycle through the ActiveWorkbook.Worksheets array, but the code is not working even if i hard-code the name myself.
Here is a larger chunk of the code, to be clearer:
Set sourceWorkbook = ActiveWorkbook
For index = 1 To sourceWorkbook.Worksheets.Count
sourceWorkbook.Activate 'not sure if this is even needed
Set currWorksheet = sourceWorkbook.Worksheets(index)
currWorksheet.Copy ThisWorkbook.Worksheets("HiddenSheet")
Next index
The result is now consistently:
Run-time Error '1004'
Copy method of worksheet class failed.
I thank everybody in advance for the help!
Some useful guidelines:
Option Explicit
'Copy sheet
Sub CopySheet()
Dim ws1 As Workbook, ws2 As Workbook
'It's better to declare sheets and avoid activate
Set ws1 = Workbooks("Book1")
Set ws2 = Workbooks("Book2")
'Copy sheet "Test" from ws1(Book1) to ws2 (Book2) after all sheets
ws1.Worksheets("Test").Copy After:=ws2.Worksheets(Sheets.Count)
End Sub
Option Explicit
'Copy a range
Sub CopyRange()
Dim ws1 As Workbook, ws2 As Workbook
'It's better to declare sheets and avoid activate
Set ws1 = Workbooks("Book1")
Set ws2 = Workbooks("Book2")
'Copy from ws1(Book1), sheet "Test" & range A1:A5 to ws2 (Book2), sheet "sheet1" & range A1
ws1.Worksheets("Test").Range("A1:A5").Copy
ws2.Worksheets("Sheet1").Range("A1").PasteSpecial Paste:=xlPasteValues
End Sub
I have a relatively simple question. Currently I have some code that is working well but not efficient. I have about 500 cost centres each with their own workbook which I have consolidated into a central repository (reference - Wb2 in code below). The code copies ranges from each open template (Wb1) into my consolidation (Wb2). Sample code below (full code not necessary).
Option Explicit
Sub CopyData()
Dim Wb1 As Workbook, wb2 As Workbook, wB As Workbook
Dim rngToCopy1 As Range
Dim rngToCopy2 As Range
Dim rngToCopy3 As Range
Dim rngToCopy4 As Range
Dim rngToCopy5 As Range
Set wb2 = ThisWorkbook
Application.Calculation = xlManual
For Each wB In Application.Workbooks
If Not Left(wB.Name, 18) = "Consolidation Test" Then
Set Wb1 = wB
Exit For
End If
Next
'Forecast Data
With Wb1.Sheets(1)
Set rngToCopy1 = .Range("A11:O11", .Cells(.Rows.Count, "A").End(xlUp))
End With
wb2.Sheets(7).Range("A" & Rows.Count).End(xlUp).Offset(1).Resize(rngToCopy1.Rows.Count, 15).Value = rngToCopy1.Value
wb2.Sheets(7).Range("P" & Rows.Count).End(xlUp).Offset(1).Resize(rngToCopy1.Rows.Count).Value = Sheets(3).Range("J1").Value
I have tried to simply change as an example wB2.Sheets(7) to Wb2.Sheets("Forecast_Data") as well as the original name in VBE wB2.Sheets("Sheet4") but I get a subscript out of range error?
In addition to the solution, please also provide background on why the fix is not so simple, has it got to do with how my variables are declared?
I think #GSerg already gave you the most important hint.
I assume you created a workbook with the name WB2, but it does not contain any of those sheets you want to write in.
Either create them manually in your template (WB2) or have a look at How to Add a Named Sheet at the end of all excel sheets to create them with your VBA.
I was looking for a way to find data in a column and using google i found this page.
How to find text in a column and saving the row number where it is first found - Excel VBA
and one of the codes i am trying to use what came from that page
With WB.Sheets("ECM Overview")
Set FindRow = .Range("A:A").Find(What:="ProjTemp", LookIn:=xlValues)
End With
i have change the code to fit my sheet but i keep getting an Object Required
i try setting the
Dim ws As Worksheet
Dim wb As Workbook
but then i just get other goofy errors not sure what im doing wrong here
the code im using for my sheet
With wb.Sheets("RR LOG")
Set FindRow = .Range("H:H").Find(What:=ProRRnumber, LookIn:=xlValues)
End With
It looks to me like you may not have set wb as anything.
Before the With statement, try adding code like:
Set wb = ActiveWorkbook
Or, if you want to explicitly assign wb to the name of a workbook, try:
Set wb = Workbooks("Book1.xlsx")
Replace Book1.xlsx with the name of the workbook you are referencing.
I know this might come off as a trivial question, but I can't seem to declare a workbook or a worksheet as a variable in VBA. I have the following code, but I can't figure out what I am doing wrong, it should be straight forward. Normally I don't have any problems declaring variables such as Dim i As Integer etc.
sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheet("name")
wb.ws.Select
End Sub
When I run the above code, I receive a type missmatch error.
Use Sheets rather than Sheet and activate them sequentially:
Sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
Set ws = Sheets("Sheet1")
wb.Activate
ws.Select
End Sub
If the worksheet you want to retrieve exists at compile-time in ThisWorkbook (i.e. the workbook that contains the VBA code you're looking at), then the simplest and most consistently reliable way to refer to that Worksheet object is to use its code name:
Debug.Print Sheet1.Range("A1").Value
You can set the code name to anything you need (as long as it's a valid VBA identifier), independently of its "tab name" (which the user can modify at any time), by changing the (Name) property in the Properties toolwindow (F4):
The Name property refers to the "tab name" that the user can change on a whim; the (Name) property refers to the code name of the worksheet, and the user can't change it without accessing the Visual Basic Editor.
VBA uses this code name to automatically declare a global-scope Worksheet object variable that your code gets to use anywhere to refer to that sheet, for free.
In other words, if the sheet exists in ThisWorkbook at compile-time, there's never a need to declare a variable for it - the variable is already there!
If the worksheet is created at run-time (inside ThisWorkbook or not), then you need to declare & assign a Worksheet variable for it.
Use the Worksheets property of a Workbook object to retrieve it:
Dim wb As Workbook
Set wb = Application.Workbooks.Open(path)
Dim ws As Worksheet
Set ws = wb.Worksheets(nameOrIndex)
Important notes...
Both the name and index of a worksheet can easily be modified by the user (accidentally or not), unless workbook structure is protected. If workbook isn't protected, you simply cannot assume that the name or index alone will give you the specific worksheet you're after - it's always a good idea to validate the format of the sheet (e.g. verify that cell A1 contains some specific text, or that there's a table with a specific name, that contains some specific column headings).
Using the Sheets collection contains Worksheet objects, but can also contain Chart instances, and a half-dozen more legacy sheet types that are not worksheets. Assigning a Worksheet reference from whatever Sheets(nameOrIndex) returns, risks throwing a type mismatch run-time error for that reason.
Not qualifying the Worksheets collection is an implicit ActiveWorkbook reference - meaning the Worksheets collection is pulling from whatever workbook is active at the moment the instruction is executing. Such implicit references make the code frail and bug-prone, especially if the user can navigate and interact with the Excel UI while code is running.
Unless you mean to activate a specific sheet, you never need to call ws.Activate in order to do 99% of what you want to do with a worksheet. Just use your ws variable instead.
Third solution:
I would set ws to a sheet of workbook wb as the use of Sheet("name") always refers to the active workbook, which might change as your code develops.
sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ActiveWorkbook
'be aware as this might produce an error, if Shet "name" does not exist
Set ws = wb.Sheets("name")
' if wb is other than the active workbook
wb.activate
ws.Select
End Sub
Just coming across the same problem.
What you need to do is to declare ws as Object
Also it should be:
Set ws = wb.Sheets("Sheet1")
And should not be:
Set ws = Sheet("Sheet1")
The code below are working to me.
sub kl()
Dim wb As Workbook
Dim ws As Object
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
MsgBox ws.Name
End Sub
Try changing the name of the variable as sometimes it clashes with other modules/subs
Dim Workbk As Workbook
Dim Worksh As Worksheet
But also, try
Set ws = wb.Sheets("name")
I can't remember if it works with Sheet
to your surprise, you do need to declare variable for workbook and worksheet in excel 2007 or later version. Just add single line expression.
Sub kl()
Set ws = ThisWorkbook.Sheets("name")
ws.select
End Sub
Remove everything else and enjoy.
But why to select a sheet? selection of sheets is now old fashioned for calculation and manipulation.
Just add formula like this
Sub kl()
Set ws = ThisWorkbook.Sheets("name")
ws.range("cell reference").formula = "your formula"
'OR in case you are using copy paste formula, just use 'insert or formula method instead of ActiveSheet.paste e.g.:
ws.range("your cell").formula
'or
ws.colums("your col: one col e.g. "A:A").insert
'if you need to clear the previous value, just add the following above insert line
ws.columns("your column").delete
End Sub
I had the same issue. I used Worksheet instead of Worksheets and it was resolved. Not sure what the difference is between them.
Dim ws as Object
Set ws = Worksheets("name")
when declaring the worksheet as worksheet instead of an ojbect I had issues working with OptionButtons (Active X) in this worksheet (I guess the same will be with any Active-X element. When declared as object everything works fine.
Lots of answers above! here is my take:
Sub kl()
Dim wb As Workbook
Dim ws As Worksheet
Set ws = Sheets("name")
Set wb = ThisWorkbook
With ws
.Select
End With
End Sub
your first (perhaps accidental) mistake as we have all mentioned is "Sheet"... should be "Sheets"
The with block is useful because if you set wb to anything other than the current workbook, it will ececute properly