I am new to Excel Add-ins and I am not sure how to write mi programm.
I would like to put in an add-in a code so that, when the workbook that uses the add-in is opened, it creates a sheet named "mainSheet".
I can use the event handler in the Workbook, but is it possible to put the code in the module of the add-in and still be able to run it?
I found this on the "Automate Excel" web site. Hope this helps
The following code works opening a workbook. It automatically adds a new sheet and labels it with the name. It also checks to see that the sheet doesn’t already exist – to allow for the possibility of it being opened more than once a day.
This code makes use of the Workbook Open Event and must be placed in the workbook module under the “Open work Book” event. The function Sheet_Exists must be placed in a module and this checks whether or not the sheet exists:
Private Sub Workbook_Open()
Dim New_Sheet_Name As String
New_Sheet_Name = "mainSheet"
If Sheet_Exists(New_Sheet_Name) = False Then
With Workbook
Worksheets.Add().Name = New_Sheet_Name
End With
End If
End Sub
==
Function Sheet_Exists(WorkSheet_Name As String) As Boolean
Dim Work_sheet As Worksheet
Sheet_Exists = False
For Each Work_sheet In ThisWorkbook.Worksheets
If Work_sheet.Name = WorkSheet_Name Then
Sheet_Exists = True
End If
Next
End Function
Related
On its own workbook "A" starts with checking if there is a settings file saved locally, that stores the User's credentials for autologin.
If there is no such file, it will show a login form.
I would like to add now the functionality that if I open workbook"A" from workbook "B" it should try to fetch the logged in user of WorkBook"B" instead of starting with checking the local settings file first.
There is a variety of WB-s that could call "A", so i would not go for putting a code in A to check a cellvalue in B, instead I would like to have B modify something in A upon opening.
The problem is:
When i open "A" from "B", any modification is only implemented after every code executed from _Open macro, so it cannot recognize in time, that actually i would like to pass extra information to that process.
like this:
Sub Test 'In Wb"B"
Dim Wb as workbook
Set Wb = Workbooks.Open(path)
Wb.Sheets(1).Range("A1").Value = "NewValue"
End sub
'----
Private Sub workbook_open() ' In Wb"A"
MsgBox ThisWorkbook.Worksheets(1).Range("A1").Value
End Sub
MsgBox will show "OldValue", because the external change will take place after the _Open event.
I have also tried to pass a parameter like _Open(optional Modifier as variant), but as I suspected, Events cannot accept parameters like that, right?
So how to provide extra info to Wb"A" from Wb"B" upon opening, before anything else happens?
One possible, but not preferred method I can think of is via command line parameters, like discussed in here:
Passing a parameter to an Excel file when opening it
Is there any other solution to achieve the requied results?
you could use the last workbook opened before "A" as a "messenger"
for instance should "B" the last opened workbook, you would have the following Test() sub:
Sub Test() 'In Wb"B"
Dim Wb As Workbook
Sheets(1).Range("A1").Value = "NewValue" ' use a convenient sheet and cell in "B" workbook to store the value you want to "pass" to "to-be-opened-soon" workbook
Set Wb = Workbooks.Open(path)
End Sub
and in "A" ThisWorkbook code pane you would then place:
Private Sub workbook_open() ' In Wb"A"
ThisWorkbook.Worksheets(1).Range("A1").Value = Workbooks(Workbooks.Count - 1).Sheets(1).Range("A1").Value 'retrieve the value from the last opened workbook
MsgBox ThisWorkbook.Worksheets(1).Range("A1").Value
End Sub
I'm very new at VBA ad I have the following problem.
I want to reference worksheets by codenames (because the tab name can be modify by the user)
I know that is not possible add a new worksheet specifying the codename.
In a running of my macro I create a new Worksheet using:
Worksheets.Add().Name = "aSheet"
st = Worksheets("aSheet").CodeName
now I have the codename in variable st.
In a following run of the macro (in one in which I don't create the new worksheets) I want to access the previous created worksheet by codename i.e. I
want to use code with codename hard coded. I don't want to use
st = Worksheets("aSheet").CodeName
because between the two runs of the macro the user must have changed the tab "aSheet" name.
That seems impossible to me, but I hope to be wrong.
Instead of going to the workbook's Worksheets collection, just refer directly to the worksheet by its codename:
debug.print Sheet5.name
You can also use it's index if you are super into the Worksheets collection:
debug.print Sheets(5).name
You might find it helpful to save the worksheet as a global variable (declared outside the scope of your function or subroutine. The global variable will be available after code execution, but will be reset if the workbook is closed and reopened.
Dim st As Worksheet
Sub addWorksheet()
Set st = ThisWorkbook.Worksheets.Add()
st.Name = "test3"
Debug.Print st.Name, st.CodeName
End Sub
That variable st is a worksheet object and can be referenced in any other subroutine or function after it's set.
...later on
Sub printWSName()
Debug.print st.name
End Sub
Finally you may want to save this value if the workbook closes. In your Workbook Object in the Project pane you can use the Workbook_BeforeClose and Workbook_Open events to save and recapture this value:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Worksheets("savedStuff").Cells(1, 1).Value = st.Name
End Sub
Private Sub Workbook_Open()
Set st = Worksheets(st.Name)
End Sub
Hi Iam new to writing VBA code and need assistance. My VBA code and Macro works fine as long as I am on the active sheet.
My Problem:
My VBA code and macro, stops running automatically, when i change from the active sheet to another within the same workbook and
My VBA code and macro, stops running automatically, when i open a new excel workbook
Solution required:
Run the VBA code and macro only on desired worksheet and prevent it from running on other worksheets and workbooks.
Background:
I have an excel file, named "Net Weight" with two sheets. sheet 1 is named : "weight", sheet 2: is named "base data".
sheet 1 is used as a user input form.
In sheet 1- cell B1 : user will type in a product code , in cell E1: a look up formula will place the description of the product code using the data from sheet 2
I have setup a VBA code and macro that does the following:
As soon as a user inputs a product code into cell B1, in sheet 1, sheet 1 is saved as PDF file into a predefined folder location data from cell B1 and E1
A macro saves and overwrties the PDF file every 10 seconds.
This process is repeated every time a new product code is entered
There are no buttons on sheet 1, everything is done automatically.
Here is my current code:
Sheet 1: set as Worksheet
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$B$1" Then
Call Macro1
End If
End Sub
Module 1 macro : set as general
Sub Macro1()
Application.DisplayAlerts = False
If ThisWorkbook.Name = "Nett Weight.xlsm" And ActiveSheet.Name = "Weight" Then
Sheets("Weight").ExportAsFixedFormat Type:=xlTypePDF, _
Filename:="C:\Nett weight\" & Range("B1 ").Text & Range(" E1").Text
Application.OnTime Now + TimeValue("00:00:10"), "Macro1"
Else
Exit Sub
End If
End Sub
First, you need to create a public variable to hold your timer, otherwise you'll never be able to cancel it so it will continue trying to fire even when your workbook is closed. You should also create a public variable to store when the timer is running, so you can check before creating a new timer.
At the top of a code module put:
Public nextTime As Date
Then in your Workbook_BeforeClose() event method (within ThisWorkbook), disable the existing timer so it doesn't keep trying to fire after the workbook is closed.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
On Error Resume Next ' Continue with next line of code if we encounter an error
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=False
On Error GoTo 0 ' Resume error-trapping
End Sub
In Macro1() you should explicitly and directly reference your workbook components - ThisWorkbook always refers to the workbook the code is running from, so you don't need your If statement. Then you set the nextTime and activate the timer using that variable if it is not already running.
Sub Macro1()
Dim sht As Worksheet ' Creates a variable to hold your Weight worksheet
Set sht = ThisWorkbook.Sheets("Weight") ' Sets the reference
Application.DisplayAlerts = False
sht.ExportAsFixedFormat Type:=xlTypePDF, Filename:="C:\Nett weight\" & sht.Range("B1").Text & sht.Range("E1").Text ' Remember to preceed Range with sht. to explicitly reference the range of your Weight worksheet
On Error Resume Next ' Continue with next line of code if we encounter an error
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=False
On Error GoTo 0 ' Resume error-trapping
nextTime = Now + TimeSerial(0, 0, 10) ' Adds 10 seconds to Now
Application.OnTime Earliesttime:=nextTime, Procedure:="Macro1", Schedule:=True
timerIsRunning = True
Application.DisplayAlerts = True ' Remember to enable alerts at the end of code
End Sub
Your Worksheet_Change() event method can stay as is. Now if there is a change in B1 it will call Macro1(). Macro1() will save the Weight worksheet as a PDF regardless of whether the workbook or worksheet is active, and create a new timer to re-run Macro1() every 10 seconds after deactivating an existing timer. When you're finished with the workbook, you close it and the existing timer is also deactivated.
EDIT:
Fortunately (as it fixes a spreadsheet of my own) I have figured out why the solution I originally provided wasn't working. Placing the Public variables under ThisWorkbook meant they no longer held their values after code execution. The remedy was to place them in a module instead. Once that was sorted out, I also realised that when the timer fires to call Macro1() it will throw an error when trying to unschedule the existing timer (as none exists unless Macro1() was called ad hoc by the Worksheet_Change() event).
Long story short: Public variables have been moved to a code module, and the timerIsRunning flag has been removed entirely and errors when attempting to unschedule the timer are simply ignored in the event that no timer exists.
I am trying to come up with some vba code to open an input box automatically as soon as the workbook is opened and have the user enter a date and then have the date placed in the A1 cell. I have written the code below but the input box is not pulling up at all it just opens the workbook and moves on.. not sure what is happening. Any and all help is appreciated.
Thanks!
Option Explicit
Private Sub workbook_open()
Dim cellvalue As Variant
Dim ws As Worksheet
Set ws = Worksheets("Workbench Report")
ReShowInputBox: cellvalue = Application.InputBox("Please Enter Todays Date (dd/mm/yyyy)")
If cellvalue = False Then Exit Sub
If IsDate(cellvalue) And CDate(cellvalue) < Date Then
ws.Range("A1").Value = DateValue(cellvalue)
Else: MsgBox ("Invalid Date!")
GoTo ReShowInputBox
End If
End Sub
Your code triggers upon the Workbook opening for me. Try these steps.
Open up Excel and Save As, changing the extension to .XSLM
Open up the VBA Editor (ALT + F11)
In the left-hand window, locate your macro file (the one you just created and named - it's in brackets after "VBA Project"), drilldown to "This Workbook" and double-click it.
Paste your code into the right-hand window
Save the file and re-open.
See attached diagram.
By the way, "cellValue = false" should probably be cellValue = "" since InputBox is returning a string and not a boolean value.
For Workbook_Open events the script needs to reside in the private module (ThisWorkbook)
From Ozgrid:
the Workbook_Open event is a procedure of the Workbook Object and as
such, the Workbook_Open procedure MUST reside in the private module of
the Workbook Object (ThisWorkbook).
I have created a custom function in Excel using VBA. I'm trying to get data from a different workbook using the Workbooks.Open(path) command. Here's my code:
Option Explicit
Function TestFunction() As String
mySub
TestFunction = "Success."
End Function
Sub mySub()
Dim path As String
Dim wk As Workbook
path = "C:\Users\jg\Desktop\machine_data.xlsm"
Set wk = Workbooks.Open(path)
Dim ws As Worksheet
Set ws = wk.Sheets(1)
Debug.Print ws.Range("A2")
End Sub
Sub Test()
Debug.Print (TestFunction())
End Sub
Now my problem is the following:
When I run the Sub Test() within the VBA environment from Excel everything works as planned. machine_data.xlsm gets opened and the field A2 shows up in debug.
Once I go to the workbook where I defined this module in and type =TestFunction() into a cell, I get a #VALUE!. The file also doesn't get opened.
If I comment these two lines:
Set ws = wk.Sheets(1)
Debug.Print ws.Range("A2")
the cell will show Success!, but the file still doesn't open.
What am I doing wrong? Both workbooks are .xlsm files. I am using Microsoft Office Excel 2007.
Just throw everything from mySub into the test function and if everything is successful have test function return the value of the cell. So testFunc = ws.Range("A2").
As DaveU already stated UDFs can only return values. I found a different workaround simply calling the function from within the VBA environment which lets me modify cell contents wherever I'd like.