Setting value of named range in Excel - vb.net

I apologize if this is a total noob question. I'm in the process of writing an addin for Excel. I have a sub inside class1 that opens an excel file, in this sub I have a reference to sub2 which is below. All I am looking to do is hook into the active instance of Excel, change a named range value and exit. But I keep getting errors no matter which way that I try. Here is what I have. Tell me where I have gone wrong. Forgot to mention, this is in VB.NET.
Private Sub SetRangeValue(ByVal RangeName As String, ByVal RangeValue As String)
Dim ExcelApp As Excel.Application
Dim TheRange As Excel.Range
Dim TheRangeName As String = ""
'Hook into running excel instance
ExcelApp = CType(Marshal.GetActiveObject("Excel.Application"), Excel.Application)
'First Attempt Here
TheRange = ExcelApp.ActiveWorkbook.Names.Item(RangeName)
TheRange.Value = RangeValue
'Second Attempt
TheRange = ExcelApp.Range(RangeName)
TheRange.Value = RangeValue
End Sub
I can't get either one to work. Any help is appreciated.

Finally I got this to work properly. This is how it needed to work. Thanks for all the help.
Private Sub SetRangeValue(ByVal RangeName As String, ByVal RangeValue As String)
Dim ExcelApp As Excel.Application
'Dim TheRangeObj As Excel.Range
Dim TheRange As Microsoft.Office.Interop.Excel.Name
Dim TheRangeName As String = ""
'Hook into running excel instance
ExcelApp = CType(Marshal.GetActiveObject("Excel.Application"), Excel.Application)
TheRange = ExcelApp.ActiveWorkbook.Names.Item(RangeName)
TheRange.RefersToRange.Value = RangeValue
End Sub

'First Attempt Here
TheRange = ExcelApp.ActiveWorkbook.Names.Item(RangeName)
TheRange.Value = RangeValue
According to Names.Item Method (Excel), this function returns a single Name object from a Names collection. In this case TheRange is not valid name for this variable, it should be TheName. Then
TheName.Value = RangeValue
is not right assignment; According to Name.Value Property (Excel) this property - Returns or sets a String value that represents the formula that the name is defined to refer to.
Error 0x800A03EC, there are a number of reasons this error is returned from Excel - the most common is when attempts to write data larger than Excel can handle. For example, you try to write a string longer than 1024 characters to a cell in Excel

I just made a sub that would make it easier me to find & replace using my named ranges:
Private Sub XlFindReplace(ByRef xSheet As Excel.Worksheet, ByVal cellName As String, ByVal NewText As String)
xSheet.Range(cellName).Value = NewText
End Sub
then T'd call it like this in order to replace stuff:
XlFindReplace(xlC1Sheet, "client1Co1Tax", client1Co1Tax)
where the xlC1Sheet is the sheet I'm currently
the "client1Co1Tax"is the name of the range in excel
and client1Co1Tax is the string variable I'm replacing it
Thanks to everyone for their input.

Related

Opening Range from a different workbook

I'm writing some VBA to check for changes to a spreadsheet when a button is clicked. The spreadsheet makes a copy of itself in the temp directory as determined by the environment variable on Workbook_Open(). This is all working fine, but the problem is with my button_click sub.
Following advice from this question, I'm trying to read the range of interest into an array. The problem is, my array is coming up empty. Is there something stupid that I'm forgetting to do here?
Dim wsOriginalWS As Worksheet
Dim varOriginalSheet As Variant
Dim wbkOrig As Workbook
Dim strRangeToCheck As String
Dim varOriginalSheet As Variant
'... some other non-relevant things
strRangeToCheck = "A5:HC231"
Set wbkOrig = Workbooks.Open(Filename:=FileStr)
Set wsOriginalWS = wbkOrig.Worksheets("Sheet1")
wsOriginalWS.Activate
With wsOriginalWS
Set varOriginalSheet = Range(strRangeToCheck)
End With
'... some other non-relevant things. At this point,
'... wbkOrig is still open, and I can see it with all of its data
'... while debugging.
itemp = getDimension(varOriginalSheet)
I have verified that everything up to Set varOriginalSheet = Range(strRangeToCheck) is working. The spreadsheet in the temp directory opens and is not empty. For some reason varOriginalSheet is empty.
Here's getDimensions:
Function getDimension(var As Variant) As Long
On Error GoTo Err
Dim i As Long
Dim tmp As Long
i = 0
Do While True
i = i + 1
tmp = UBound(var, i)
Loop
Err:
getDimension = i - 1
End Function

VBA - Storing a range into a Range Property on a user class

I have a class that has the following definition:
Private pvtRngTest1 As Range
Public Property Get RngTest1() As Range
Set RngTest1 = pvtRngTest
End Property
Public Property Set RngTest1(ByVal rng As Range)
Set pvtRngTest1 = rng
End Property
When I'm using this class, I'm trying:
Sub FindAllTablesOnSheet(oSh As Worksheet)
Dim oLo As ListObject
For Each oLo In oSh.ListObjects
MsgBox "Table found: " & oLo.Name & ", " & oLo.Range.Address
Dim sr As SheetRanges
Set sr = New SheetRanges
Set sr.RngTest1 = oLo.Range
MsgBox sr.RngTest1.Address
Next
End Sub
I get an error: Object Required (on the last line within the Next statement)
Can someone please help explain? I believe I'm setting the Range property correctly, I get no error when I set it, but then I cannot access the Address of that property.
As https://stackoverflow.com/users/3598756/user3598756 said above, it was typo. Been about 10 years since I looked at VBA and overlooked the benefits of Option Explicit. :S

Range.Formula error with user defined functions

Hello guy I have a user defined function inside VBA
Function clean(word As String, ParamArray characters() As Variant) As String
For i = 0 To UBound(characters)
word = Replace(word, characters(i), "")
Next i
clean = word
End Function
whenever I try to use it in another subroutine like that
Sub prova()
Dim wb As Workbook
Dim wsB As Worksheet
Set wb = ThisWorkbook
Set wsB = wb.Sheets("Bond Holdings")
wsB.Range("R3").Formula = "=clean(""dfsduuu"",""u"")"
End Sub
I get runtime error 1004. Could you guys help me figure out why? this is driving me crazy.
Thank you
Excel has a built-in function called CLEAN. You have a name-clash. If you call your function e.g. cleaner, it will work as expected.

Refactor code to break links so Variant type is not used

How do I refactor the following sub-routine so it does not use the Variant data type?
Sub BreakAllLinks()
Dim Link As Variant
Dim myLinks As Variant
myLinks = Excel.ActiveWorkbook.LinkSources(Type:=Excel.xlLinkTypeExcelLinks)
For Each Link In myLinks
Excel.ActiveWorkbook.BreakLink Name:=Link, Type:=Excel.xlLinkTypeExcelLinks
Next Link
End Sub
Here's how you could do it with no Variants - but you shouldn't.
Sub BreakAllLinks()
Dim myLinks() As String
Dim LinkIdx As Long
Dim Link As String
ReDim myLinks(1 To UBound(ActiveWorkbook.LinkSources(xlLinkTypeExcelLinks)))
For LinkIdx = LBound(myLinks) To UBound(myLinks)
myLinks(LinkIdx) = ActiveWorkbook.LinkSources(xlLinkTypeExcelLinks)(LinkIdx)
Next LinkIdx
For LinkIdx = LBound(myLinks) To UBound(myLinks)
Link = myLinks(LinkIdx)
ActiveWorkbook.BreakLink Link, xlLinkTypeExcelLinks
Next LinkIdx
End Sub
That's a little over-the-top on purpose to demonstrate all the data types involved. You can only For..Each an array with a Variant - it's just how the language is written. The best practice isn't 'don't use Variants' but rather 'Use the most restrictively typed variable that you can'. In your case, the Variant is the most restrictively typed variable you can use.
There is a way to write that without Variants and not so obviously crazy
Sub BreakAllLinks()
Dim LinkIdx As Long
For LinkIdx = LBound(ActiveWorkbook.LinkSources(1)) To UBound(ActiveWorkbook.LinkSources(1))
ActiveWorkbook.BreakLink ActiveWorkbook.LinkSources(1)(1), xlLinkTypeExcelLinks
Next LinkIdx
End Sub
But even then, I'd opt for the Variant. It's worth the trade off.
A Linksource is a String.
But why bother ?
Sub M_snb()
For Each it In ActiveWorkbook.LinkSources(1)
MsgBox = TypeName(it)
ActiveWorkbook.BreakLink it, 1
Next
End Sub

vba: return dictionary from function

this outlines what i am trying to do.
this is not working for me, and it is unclear why.
thank you in advance for any and all help.
Sub mySub()
dim myDict as Dictionary
myDict=new Dictionary
myDict=myFunc()
End Sub
Function myFunc()
dim myDict2
set myDict2 = new Dictionary
'some code that does things and adds to myDict2'
myFunc=myDict2
End Function
You'll need to use the SET keyword anytime you are assigning an object instead of a value:
Sub mySub()
dim myDict as Dictionary
set myDict = myFunc()
End Sub
Function myFunc() as Dictionary
dim myDict2 as Dictionary
set myDict2 = new Dictionary
'some code that does things and adds to myDict2'
set myFunc=myDict2
End Function
Your original code was also creating myDict as a new Dictionary object, then immediately replacing it with a different one. You can just skip that step.
I see that this is an old question, but the post AND solution helped me figure this out, and I took it to the next level. It was a small leap. Thank you!
How about converting your function that populates the dictionary with process names and IDs so it returns a dictionary object? Then it is a simple task of populating a sheet with the dictionary contents, which I learned to do from a blog. I wish I had the author's name but the link is included.
Sheet1 was assumed of course. Customize however you wish. Again this was a small leap from what both of you posted. Absolutely brilliant work guys, thank you!
Sub Test_AllRunningApps()
Dim apps As Dictionary
Set apps = AllRunningApps()
'Populate a sheet with a dictionary - http://exceldevelopmentplatform.blogspot.com/2018/05/vba-writing-dictionaries-to-worksheet.html
Sheet1.Cells(1, 1).Resize(apps.Count, 1).Value2 = Application.Transpose(apps.Keys)
Sheet1.Cells(1, 2).Resize(apps.Count, 1).Value2 = Application.Transpose(apps.Items)
Set apps = Nothing
End Sub
'Similar to: http://msdn.microsoft.com/en-us/library/aa393618%28VS.85%29.aspx
Public Function AllRunningApps() As Dictionary
Dim strComputer As String
Dim objServices As Object, objProcessSet As Object, Process As Object
Dim oDic As Object, oDic2 As Object, a() As Variant
Set oDic = CreateObject("Scripting.Dictionary")
strComputer = "."
Set objServices = GetObject("winmgmts:\\" _
& strComputer & "\root\CIMV2")
Set objProcessSet = objServices.ExecQuery _
("Select Name, ProcessID FROM Win32_Process", , 48)
For Each Process In objProcessSet
If Not oDic.exists(Process.Name) Then
oDic.Add Key:=Process.Properties_("Name").Value, Item:=Process.Properties_("ProcessID").Value
End If
Next
Set AllRunningApps = oDic
Set objProcessSet = Nothing
Set oDic = Nothing
End Function