Late bound resolution using COM objet for Excel - vb.net

The following is inside an SSIS script task using VB.net
I have read a bit into this error, and it seems that something is wrong with this line:
worksheet = CType(workbook.Sheets(4), Excel.Worksheet)
My code is below. I think it will be simple for the more experienced folks here.
text:
Public Sub Main()
Dim excel As New Excel.Application
Dim filename As String = "S:\UK\Clients\Direct\xxxxxxx.xls"
excel.Visible = True
excel.DisplayAlerts = False
Dim workbook As Excel.Workbook
workbook = excel.Workbooks.Open(filename, , False) 'True = ReadOnly
Dim worksheet As Excel.Worksheet
worksheet = CType(workbook.Sheets(4), Excel.Worksheet)
worksheet.Rows(1).delete()
Dts.TaskResult = ScriptResults.Success
End Sub

add Option Strict Off at the top of your code, This will allow late binding.
To know Early vs. Late Binding , refer here
you can replace this statement
worksheet.Rows(1).delete()
with
Dim rw As Excel.Range
rw = CType(worksheet.Rows(1), Excel.Range)
rw.Delete()
And set Option Strict On at the top
All your code will be early bound. Hope this helps

Related

Get Excel Object when Option Strict On

I have got following codes from this microsoft page.
https://msdn.microsoft.com/en-us/library/e9waz863(v=vs.90).aspx
' Add Option Strict Off to the top of your program.
Option Strict Off
.
Private Sub getExcel()
Dim fileName As String = "c:\vb\test.xls"
If Not My.Computer.FileSystem.FileExists(fileName) Then
MsgBox(fileName & " does not exist")
Exit Sub
End If
' Set the object variable to refer to the file you want to use.
Dim excelObj As Object = GetObject(fileName)
' Show Excel through its Application property.
excelObj.Application.Visible = True
' Show the window containing the file.
Dim winCount As Integer = excelObj.Parent.Windows.Count()
excelObj.Parent.Windows(winCount).Visible = True
' Insert additional code to manipulate the test.xls file here.
' ...
excelObj = Nothing
End Sub
Everything is okey when Option Strict Off
Everything is not okey when Option Strict On
So, how to solve that errors when Option Strict On?
Be careful! I want to get specific excel file from the same excel instance.
+1 for striving to use Option Strict On. :)
However, the code is using what is known as Late Binding and that requires you have Option Strict Off. You can however, minimize the scope of Option Strict Off by creating a new code file and using a Partial Class definition to contain the code that needs Late Binding.
You might be able to get by using the VB CallByName function with Option Strict On, but that would get ugly real quick and probably be very slow.
There also is an advanced technique using native API's that is called COM reflection that should work with Option Strict On. This technique is described in the article: [Basic Instincts - Inspecting COM Objects with Reflection].(https://msdn.microsoft.com/en-us/magazine/dd347981.aspx).
The typical method for early binding (Option Strict On) is to add a reference to the Excel primary interop assembly. This technique has some detractors as well, but is by far the easiest method.
Edit: The following demonstrates how to use the Excel PIA's and early binding to open a workbook directly similar to the OP's original code.
Dim wbPath As String = "*** replace with path to your workbook ***"
Dim wb As Excel.Workbook = CType(GetObject(wbPath), Excel.Workbook)
'or
'Dim wb As Excel.Workbook = CType(Marshal.BindToMoniker(wbPath), Excel.Workbook)
Dim app As Excel.Application = wb.Application
app.Visible = True
wb.Windows(1).Visible = True
As a side note, there is no need to depend on the Interop.Excel early binding, if you know that it works. You can change the Error Notifications to Warning and still compile and run.
' Imports Microsoft.Office.Interop.Excel
Dim fileName = "c:\vb\test.xls"
If Not IO.File.Exists(fileName) Then MsgBox(fileName & " does not exist") : Exit Sub
Dim obj = GetObject(fileName, "Excel.Application")
Dim wb = TryCast(obj, Workbook)
wb.Application.Visible = True
wb.Windows(1).Visible = True

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.

How To Develop My Own Excel Add-in in VB.Net

I am trying to create an Excel Add-in using Vb.Net. I've started an Excel 2007 Add-in Project in VS2010. Sadly, I am not good with vb.net; I am more a VB6 developer in this regard, and my ThisAddin.vb code is:
Public Class ThisAddin
Private Sub ThisAddIn_Startup() Handles Me.Startup
End Sub
Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
End Sub
' test function; simple
Public Function getRowCount() As Long
Dim thisWB As Workbook = Me.Application.ThisWorkbook
Dim activWS As Worksheet
activWS = thisWB.ActiveSheet
Return activWS.UsedRange.Rows.Count
End Function
End Class
I've also added a Ribbon item (via Add New Item... menu option) in designer mode (not xml) - and then add a button. Then I go to code and try to call the function and I get this error when using:
MsgBox(Globals.ThisAddIn.getRowCount())
Which I got from this link: Calling a procedure within another class
To be honest, I've been trying a myriad things and I've been getting so many errors. I've been looking online as well for a tutorial on creating my own Excel Addin from scratch with no real luck. I would like not to use Add-In-Express since that's a third party app and I have to create an Excel add-in for my company from scratch.
Does anyone have an idea on how I can create a vb.net coded Excel Addin (2007) that I can use as a template or guide? I've tried several and many rely on Add-In-express and I really cannot go that way. I have a lot of VBA code (natural VBA so it's in a module in an my excel files' VBA/Developer section) and I think I can translate those from VBA/VB6 to VB.Net format so that's not my concern. It is really about getting to code my own Excel Addin in VB.Net. Any help would really be great. Thank you.
*note: I would also like not to have to ask coworkers (or do myself) to just add to the quick access toolbar the functions and subs I've created since that's really not a solution, considering that those buttons will be there when they create or open another workbook. Essentially, I've got to create my own excel addin in vb.net. Thank you once again.
The issue has to do with the definitions in Microsoft.Office.Tools.Excel and Microsoft.Office.Interop.Excel. To code an "Interop" version you could use this:
Public Function getRowCount() As Long
Dim thisWB As Excel.Workbook = Application.ActiveWorkbook
Dim activWS As Excel.Worksheet = CType(thisWB.ActiveSheet, Excel.Worksheet)
Return activWS.UsedRange.Rows.Count
End Function
To extend the functionality of the Native objects and use VSTO, you could do it like this:
Public Function getRowCount() As Long
Dim NativeWorkbook As Excel.Workbook = Application.ActiveWorkbook
Dim NativeWorksheet As Excel.Worksheet = CType(NativeWorkbook.ActiveSheet, Excel.Worksheet)
Dim thisWB As Workbook = Nothing
Dim activWS As Worksheet = Nothing
If NativeWorkbook IsNot Nothing Then
thisWB = Globals.Factory.GetVstoObject(NativeWorkbook)
End If
If NativeWorksheet IsNot Nothing Then
activWS = Globals.Factory.GetVstoObject(NativeWorksheet)
End If
Return activWS.UsedRange.Rows.Count
End Function
This is a function you can put in ThisAddin.vb that will create a new Worksheet. Note that this function names the Worksheet and adds it to the end.
Public Function AddWorkSheet(sheetName As String) As Worksheet
Dim wk = Application.ActiveWorkbook
Dim ws As Worksheet = Nothing
Try
ws = CType(wk.Sheets.Add(, wk.Sheets(wk.Sheets.Count)), Worksheet)
ws.Name = sheetName
Catch ex As Exception
Throw
Finally
AddWorkSheet = ws
End Try
End Function
To use this outside of ThisAddin.vb you could do something like this:
Dim ws As Excel.Worksheet
Dim newSheetName As String
.
'
ws = Globals.ThisAddIn.AddWorkSheet(newSheetName)

'DBNull' Error when attempting to set a range in VB.net. Database is Excel

I've written a pretty useful macro within Excel in VBA and am attempting to transfer it to a stand-alone windows application written in VB.net. I've found all the referencing pretty confusing and am now facing trouble in converting the general syntax of my code.
I'm pasting below the relevant code:
Dim ElevenSheets As Excel.Worksheet
Dim TwelveSheets As Excel.Worksheet
Dim ThirteenSheets As Excel.Worksheet
Dim WorkingSheet As Excel.Worksheet
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
xlApp = New Excel.Application
xlWorkBook = xlApp.Workbooks.Open("FILENAME.xls") 'Removed file name for company confidentiality purposes.
ElevenSheets = xlWorkBook.Worksheets("2011")
TwelveSheets = xlWorkBook.Worksheets("2012")
ThirteenSheets = xlWorkBook.Worksheets("2013")
WorkingSheet = xlWorkBook.Worksheets("WorkingSheet")
...
Cell = WorkingSheet.Range("B3") '<--- This line causes the error.
CurrentCell = (Cell.Row & "," & Cell.Column)
CurrentRow = Cell.Row
MyColumn = (Cell.Column)
CurrentCell = (CurrentRow & "," & MyColumn)
So, as you can see I've pointed out the line that gives me an error. I'm trying to set a range names "Cell" and the error "MissingMemberException unhandled No default member found for type 'DBNull'" presents itself.
Does anyone know what I've done wrong? I'm sure it's something very simple with my syntax but am finding this whole process difficult and also finding it difficult to understand other reasonably similar topics on the internet.
Thanks for bothering to ready this and let me know if you need more context,
Josh
I dont see any constructor for Cell. Also you dont have to explicitly declare all those worksheets. You can simply call them using something like xlWorkBook("WorkingSheet").Range("B3")
I have fixed the problem through trial and error. The way I did it was simply change these declarations:
ElevenSheets = xlWorkBook.Worksheets("2011")
TwelveSheets = xlWorkBook.Worksheets("2012")
ThirteenSheets = xlWorkBook.Worksheets("2013")
WorkingSheet = xlWorkBook.Worksheets("WorkingSheet")
To this:
ElevenSheets = CType(xlWorkBook.Worksheets(1), Excel.Worksheet)
TwelveSheets = CType(xlWorkBook.Worksheets(2), Excel.Worksheet)
ThirteenSheets = CType(xlWorkBook.Worksheets(3), Excel.Worksheet)
WorkingSheet = CType(xlWorkBook.Worksheets(4), Excel.Worksheet)
I don't know whether changing the sheet names to the sheet number fixed it or the CType fixed it. But one of them did.
Thank-you for your contributions!

Unable to open a specif worksheet from VB.NET (What is wrong with this code?)

Private Sub Button11_Click()
Dim oXL4 As New Excel.Application
Dim oWB4 As Excel.Workbook
Dim oSheet4 As Excel.Worksheet
If ComboBox10.Text = "abc" Then
oWB4 = oXL4.Workbooks.Open("D:\blah\blah\Def.xlsx")
oSheet4 = oWB4.Worksheets(2).Activate
oXL4.Visible = True
oXL4.UserControl = True
End If
End Sub
Error/Exception:
System.InvalidCastException was unhandled
Message=Unable to cast object of type 'System.Boolean' to type 'Microsoft.Office.Interop.Excel.Worksheet'.
What is wrong with this code?
Thanks in advance.
Activate does not return a worksheet (it's a sub).
oSheet4 = oWB4.Worksheets(2)
oSheet4.Activate()