Methods in EXCEL Addin - XLL - vba

How do I know which methods are available in my XLL module, in case i need to use / call any of them in my VBA code.
I can do this by calling the:
Application.Run()
method, in which I have to pass my macro-name as the parameter.
My question is about this macro-name: how do I know which macros are present in my XLL addin.
Any help is appreciated.
Cheers!!!!!!!!!!!
Tushar

You can use the Application.RegisteredFunctions method to give you a list of the functions in the XLLs that Excel has registered.
For example, the following code will list the XLL, the function name and the parameter types for the XLLs that are currently registered:
Public Sub ListRegisteredXLLFunctions()
Dim RegisteredFunctions As Variant
Dim i As Integer
RegisteredFunctions = Application.RegisteredFunctions
If IsNull(RegisteredFunctions) Then
Exit Sub
Else
Dim rng As Range
Set rng = Range("A1")
Set rng = rng.Resize(UBound(RegisteredFunctions, 1), UBound(RegisteredFunctions, 2))
rng.Value = RegisteredFunctions
End If
End Sub

Are you asking this from a code P.O.V? If you just want to check it out manually you can see that in the project explorer. Otherwise, I'd suggest just attempting to run the macro, but use an error handler in case the macro doesn't exist.
On Error GoTo badMacroCall
application.run(myMacro)
badMacroCall:
msgbox("That macro could not be run!")

Related

How do I find out why I get an error when writing to an Excel cell with VBA?

I'm still fairly new to VBA and struggling with its limitations (and mine!). Here's my code:
Sub updateCache(CacheKey As String, CacheValue As Variant)
Dim DataCacheWorksheet As Worksheet, CacheRange As Range, Found As Variant, RowNum As Integer
Set DataCacheWorksheet = ThisWorkbook.Worksheets("DataCache")
Set CacheRange = DataCacheWorksheet.Range("A1:B999")
Set Found = CacheRange.Find(What:=CacheKey)
If Found Is Nothing Then
RowNum = CacheRange.Cells(Rows.Count, 2).End(xlUp).Row
DataCache.Add CacheKey, CacheValue
On Error Resume Next
DataCacheWorksheet.Cells(1, 1).Value = CacheKey
DataCacheWorksheet.Cells(1, 2).Value = CacheValue
Else
'Do other things
End If
End Sub
When I step through the code, Excel simply exits the sub at the line DataCacheWorksheet.Cells(1, 1).Value = CacheKey, with no error. So, two questions:
What's the bug that's preventing the value from being updated?
Why does Excel ignore my On Error command?
Edit: If I run the line in the IDE's "Immediate" box, I get the error "Run-time error '1004' Application-defined or object-defined error. I get the same error regardless of the value of CacheKey (I tried Empty, 1234 and "Hello").
Edit 2: If I modify the sub so that CacheKey and CacheValue are hardcoded and the reference to DataCache is removed, and then I run the sub standalone it works. So why doesn't it work when called from another function? Is it possible that Excel is locking cells while doing calculations?
Not sure if this applies, but you mentioned you were calling this macro from another function. If you are calling it from a function, depending on how you are calling it, that would explain your problem. For example, a worksheet function entered into a cell cannot modify another cell on the worksheet. And the attempt to do so will result in the macro merely exiting at that point, without throwing a VBA error.
How to work around this depends on specifics you have yet to share. Sometimes, worksheet event code can be useful.
Ok, wasn't about to write an answer, but there are 3 things you should modify in your code:
Found As Range and not As Variant
RowNum As Long in case it's a row after ~32K
To trap errors usually On Error Resume Next won't help you, it will just jump one line of code. You need to handle the error situation.
Modified Code
Sub updateCache(CacheKey As String, CacheValue As Variant)
Dim DataCacheWorksheet As Worksheet, CacheRange As Range, Found As Range, RowNum As Long ' < use Long instead of Integer
Set DataCacheWorksheet = ThisWorkbook.Worksheets("DataCache")
Set CacheRange = DataCacheWorksheet.Range("A1:B999")
Set Found = CacheRange.Find(What:=CacheKey)
If Found Is Nothing Then ' check if not found in cache (*Edit 1)
RowNum = CacheRange.Cells(Rows.Count, 2).End(xlUp).Row
DataCache.Add CacheKey, CacheValue ' I assume you have a `Dictionary somewhere
' On Error Resume Next <-- Remove this, not recommended to use
DataCacheWorksheet.Cells(1, 1).Value = CacheKey
DataCacheWorksheet.Cells(1, 2).Value = CacheValue
Else
'Do other things
End If
End Sub

Excel Macro For Data Analysis

I'm building a spreadsheet macro that copies cells from one spreadsheet called DATA to a tab called REPORT based on criteria. If the criteria changes, the list clears and it adds the values that meet the new criteria. The macro is:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range("B2:C5")
If Not Application.Intersect(KeyCells, Target) _
Is Nothing Then
For iRow = 2 To 5845
If Worksheets("DATA").Range("F" & iRow).Value = False Then
'Do nothing
Else
Worksheets("WORK").Cells(iRow, 1).Value = Worksheets("DATA").Cells(iRow, 4).Value
End If
Next iRow
End If
Call Worksheets("WORK").Delete_Blank_Rows
Sheets("REPORT").Range("E1:E5845").Value = Sheets("WORK").Range("A1:A5845").Value
Worksheets("REPORT").Columns(6).ClearContents
End Sub
Sub Delete_Blank_Rows()
On Error Resume Next
With Worksheets("WORK").Range("A2:A5845")
.Value = .Value
.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End With
End Sub
The spreadsheet is here: https://drive.google.com/file/d/1G-RQ9DvGKa_EEapcLIWDf3_SCdql_dJJ/view?usp=sharing
The error I receive is
runtime error saying object doesn't support property or method.
Any help is appreciated!
Your Call method of your worksheet object appears to be causing the issue.
You are attempting to call a SUB by using it as a child object of a worksheet:
Call Worksheets("WORK").Delete_Blank_Rows
needs to be changed to
Delete_Blank_Rows
Also, remove the Call keyword. You don't need it.
Call Statement (Visual Basic)
You can use the Call keyword when you call a procedure. For most procedure calls, you aren’t required to use this keyword.
You typically use the Call keyword when the called expression doesn’t start with an identifier. Use of the Call keyword for other uses isn’t recommended.

Excel VBA Retrieve Constant from Worksheet Code Fails When New Code is Written

In an attempt to retrieve constants from each worksheet in some reporting workbooks I use, three years ago I wrote some code that gets included in each worksheet. Here's an example of the code:
Option Explicit
' Determine the type of worksheet
Private Const shtType As String = "CR"
Public Function GetShtType()
GetShtType = shtType
End Function
In other code that gets the values from the worksheets for processing, the following section of code is used, where 'wksToCheck' is the worksheet in question. This code is stored in a personal macro workbook, not in the workbook with the worksheet code:
' Get the sheet 'type' if it has one
On Error Resume Next
shtType = wksToCheck.GetShtType()
If Err.Number <> 0 Then
' We do not have a type
shtType = "Unknown"
Err.Clear
End If ' Err.Number...
On Error GoTo Error_BuildTemplateWbk
My problem is, I use the code above to process workbooks several times a week, and I have for the past three years. Now, I am trying to write some new code with the above block to process the report workbooks in a different way. However, when I run code with the above block now, I get a 'Method or Data Member Not Found' error on the '.GetShtType()' portion of the code. I cannot compile the code and of course, consequently, the code doesn't work. I have tried adding the worksheet code to a worksheet in the macro workbook to see if that would fix the problem. It hasn't. Does anyone have any ideas? I am running Excel 2013 on a Windows 7 PC. Any ideas?
Brian
Using late-binding, should avoid the error, Dim wksToCheck As Object, but you'll lose the intellisense.
If you're open to alternatives, you may have better luck simply using the CallByName function, or using worksheet's CustomProperties.
Using CallByName preserves backwards compatibility with your older workbooks if needed:
shtType = CallByName(wksToCheck, "GetShtType", VbMethod)
Or, using CustomProperties instead of a custom method, in your worksheets:
Private Sub Worksheet_Activate()
Const PropName$ = "ShtType"
Const ShtType$ = "CR"
On Error Resume Next
Me.CustomProperties(PropName) = ShtType$
If Err.Number = 13 Then
Me.CustomProperties.Add "PropName", ShtType
End If
End Sub
Then,
' Get the sheet 'type' if it has one
On Error Resume Next
shtType = wksToCheck.CustomProperties("ShtType")
If Err.Number = 13 Then
' We do not have a type
shtType = "Unknown"
Err.Clear
End If ' Err.Number...
On Error GoTo Error_BuildTemplateWbk

Excel VBA Can't access sheet on external workbook

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.

Why does Excel VBA prompt me for a Macro name when I press Run Sub

I have the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim RR As Range
Dim TestArea As Range
Dim foremenList As Range
Dim workerList As Range
Dim workers As Range
Dim Foremen As Range
Dim i As Integer
Dim R As Range
Dim EmplList() As Variant
Set TestArea = Sheet90.Range("b4:q8", "b15:q19", "b26:q30")
Set foremenList = Sheet90.Range("V24:V30")
Set RR = Sheet90.Range("AA25:AA46")
i = 0
For Each R In RR.Cells
If Len(R.Value) > 0 Then
EmplList(i) = R.Value
i = i + 1
End If
Next R
Dim ValidStr As String
Set ValidStr = Join(EmplList, ",")
With Sheet90.Range("b26").Validation
.Delete
.Add xlValidateList, xlValidAlertStop, _
xlBetween, "1,2,3"
End With
Sheet90.Range("b40").Value = "Test"
End Sub
But when I press run to test it, it prompts me for a macro name.
Additionally, it does not trigger on Worksheet_Changeany more.
Is this an error (i.e. I forgot a semicolon or something) that consistently triggers Excel VBA to behave like this? If so, what should I look for in the future?
The reason you can't run this one with the Run Sub button is because it requires a parameter. If you want to run this standalone, one possibility is to run it in the Immediate Window so you can manually pass in the parameter. Since this one is expecting a more complex data type (range) you may want to create a small sub to call it so that you can properly create your range and pass that in. Then you can use the Run Sub on this sub which will call your other one.
As far is it not triggering on Worksheet_Change, I am not able to tell what is causing it just from what you posted. However, you do need to make sure that it is located on the code page for the worksheet you are trying to run it from. If you need the same one to run from multiple sheets, you should put it into a module and call it from each sheet's Worksheet_Change method.
You can't press F5 or the run button to run triggered code. You would have to make a change in the sheet where this code is located in order for the code to run. Also, if this code is not located in Sheet90, then you won't see anything happen because this code only makes changes to Sheet90. Lastly, to make sure events are enabled, you can run this bit of code:
Sub ReEnable_Events()
Application.EnableEvents = True
End Sub
Note that you will still have to enable macros.
The problem stems from two lines:
Set ValidStr = Join(EmplList, ",")
was not a valid use of the Set keyword (It's a string and not an object), and
Set TestArea = Sheet90.Range("b4:q8", "b15:q19", "b26:q30")
apparently has too many arguments.
According to Microsoft, it should be a single string argument like:
Set TestArea = Sheet90.Range("b4:q8, b15:q19, b26:q30")
Commenting both of these out made the code run fine both with the run sub button, and on the event.
The "Name Macro" dialog is some kind of error indicator, but I still don't know what it means, other than Code Borked