Preview/Print MS Access Report from Visual Basic - vb.net

I have an Visual Basic 2013 program which connects to a MS Access 2010 database. After the program calculates and writes values out to the DB, I need to print a report that is in the Access DB.
I have read through this: How To Automate Microsoft Access From Visual Basic .NET
I found similar questions such as this: Vb.Net preview report from access database but they do not use the DoCmd.OpenReport method.
The code I have now is as follows:
Imports Access = Microsoft.Office.Interop.Access
Public Class FrmReports
Dim oAccess As Access.application
Private Sub btnSumByPlan_Click(sender As Object, e As EventArgs) Handles btnSumByPlan.Click
oAccess = CreateObject("Access.Application")
oAccess.visible = True
oAccess.opencurrentdatabase ("Provider=Microsoft.ACE.OLEDB.12.0;DataSource=|DataDirectory|\CLI_CRVM.accdb")
oAccess.docmd.openreport(ReportName:="SumByPlan", View:=Access.AcView.acViewPreview)
End Sub
End Class
This code compiles but gives me the following error when it runs:
An unhandled exception of type 'System.InvalidCastException' occurred in CLI CRVM.exe
Additional information: Unable to cast COM object of type 'Microsoft.Office.Interop.Access.ApplicationClass' to class ype 'CLI_CRVM.Access.applicationclass'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
Thanks in advance.

The argument to the OpenCurrentDatabase() method of an Access.Application object is just the location of the database file, not an OLEDB connection string. Your statement should be something more like
oAccess.OpenCurrentDatabase("C:\path\to\CLI_CRVM.accdb")
Also, I am unable to say for certain if |DataDirectory| is meaningful in that context, but I highly doubt it.

Related

Create an object in Visual Basic (not VB.NET) without using "New"

I've been told to think outside the box, and think of a way to create an object in VB without using the new keyword. I was told it is possible but i'm having trouble figuring it out. I know primitive data gets stored on the stack and the reference to the objects get stored there too but the actual memory space for the object is in the heap and that new does that for us. When i try it without new i mostly get null reference exception, any ideas on how this is possible?
Dim objTest as TestOne()
'some class named TestOne with empty Constructor
In VB you can use the CreateObject function if you have an existing class defined in a COM library that you've created - or a COM library that already exists.
As an example, create a project reference to the Microsoft Scripting Runtime COM library (scrrun.dll). To do this in the VB IDE select Project, References, then pick the reference 'Microsoft Scripting Runtime'. You can then write the following code:
Dim fso As Object
fso = CreateObject("Scripting.FileSystemObject")
I haven't done VB for quite a while now, but the Activator exists in both C# and VB. Here's couple lines of C# that you can convert to VB:
var newThing = (TestOne)Activator.CreateInstance(typeof(TestOne));
newThing.ID = 5;
The CreateInstance method returns an object, which I convert to the correct class with
(TestOne)
which is the C# syntax for type conversion. Sorry, I forgot how to do this in VB.
Where class 'TestOne' looks like:
class TestOne {
public int ID { get; set; }
}
Note that 'Activator' is part of .NET reflection.

vba Run-time error '429': ActiveX can't create object, with user defined vb.net dll (VB.NET 2017, Excel 2016)

I have written a simple dll in VB.NET 2017, and I am trying to call it from VBA (Excel 2016). I have searched through Stack Overflow and MSDN, but despite many hits for this VBA error, I cannot find information related to a user defined dll that solves this particular problem.
I checked the box for the Register for COM Interop option when compiling the dll. I also verified that the Make assembly COM-Visible box was also checked.
Compilation was successful, and I was able to find my library (called TestLibrary2) in References inside the VBA editor. The class I created in it is called TestVBNET. I checked TestLibrary2 to include it in VBA, and then attempted to run the following code in VBA:
Public Sub mySub()
Dim myTest2 As TestLibrary2.TestVBNet
Set myTest2 = New TestLibrary2.TestVBNet
End Sub
When I ran the sub, I got the pop-up dialog with message: Run-time error '429': ActiveX can't create object
Based on what I have read on MSDN and other sites, the expected result is that the TestLibrary2.TestVBNet object should be instantiated successfully.
The code below is the VB.NET code that I compiled to the dll. The GUID's were generated using guidgen at the Windows 10 command prompt.
Imports System.Runtime.InteropServices
<Guid("2CEBF80D-D5FC-4C52-BCF1-E2F076318240")>
Public Interface ITestVBNet
Function addTrig(x As Double, y As Double) As Double
End Interface
<Guid("60983277-A724-4CDD-8ACE-B94CF9546F43")>
<ClassInterface(ClassInterfaceType.None)>
Public Class TestVBNet
Function addTrig(x As Double, y As Double) As Double
Return Math.Sin(x) + Math.Cos(x)
End Function
End Class
Any help and or references would be greatly appreciated. Thanks in advance.
EDIT (per comments below): I compiled the dll as admin, which in fact was required for the Register for COM Interop option to run. I also tried using regasm -- also as admin -- as follows, in the same directory as the compiled dll:
regasm /codebase /tlb TestLibrary2.dll
The following was returned:
RegAsm : warning RA0000 : Registering an unsigned assembly with /codebase can cause your assembly to interfere with other applications that may be installed on the same computer. The /codebase switch is intended to be used only with signed assemblies. Please give your assembly a strong name and re-register it.
Types registered successfully
RegAsm : error RA0000 : An error occurred while saving the exported type library: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
I apologize for being a newb here with respect to registering COM libraries, but what this seemed to indicate was the dll was registered successfully, but could not be transferred to the GAC. It was my intention not to transfer it. When I tried loading it in VBA, the same error as above occurred.
It turns out that the above code compiled to a dll that was indeed callable from a C# client. The problem with VBA, however, was that I neglected to put Implements ITestVBNet following the derived class declaration. In VB.NET, though, in addition to this, one must also explicitly indicate function overriding in the derived function declaration as well; viz (scroll all the way to the right to see the entire line),
Public Function addTrig(x As Double, y As Double) As Double Implements ITestVBNet.addTrig
By replacing the derived class above with the following, I was able to create an instance of the TestVBNet object in VBA and call the addTrig(.) method successfully:
<Guid("60983277-A724-4CDD-8ACE-B94CF9546F43")>
<ClassInterface(ClassInterfaceType.None)>
Public Class TestVBNet
Implements ITestVBNet
Public Function addTrig(x As Double, y As Double) As Double Implements ITestVBNet.addTrig
Return Math.Sin(x) + Math.Cos(x)
End Function
End Class

Office Developer tools: Can't cast System._Comobject to excel types [duplicate]

This question already has answers here:
Try to open my Excel file using C# and get an error
(3 answers)
Closed 6 years ago.
I am trying to communicate with Excel through Visual Studio, using the Office Developer Tools, but cannot seem to cast the System._comobject objects to the Microsoft.Office.Tools.Excel types:
Private Sub ThisAddIn_Startup() Handles Me.Startup
Me.Application.Workbooks.Add()
Me.Application.Worksheets.Add()
Dim sheet2 = Me.Application.Worksheets.Item(1)
Dim cell = sheet2.range("A2")
cell.Value = sheet2.GetType.ToString()
Dim tmpSheet As Microsoft.Office.Tools.Excel.Worksheet = Me.Application.Worksheets.Item(1)
End Sub
When I run this code, the cell A2 contains "System._ComObject" But I get an exception when casting it to the Worksheet type. The exception is:
Unable to cast COM object of type 'System.__ComObject' to interface
type 'Microsoft.Office.Tools.Excel.Worksheet'. This operation failed
because the QueryInterface call on the COM component for the interface with
IID '{297DC8D9-EABD-45A1-BDEF-68AB67E5C3C3}' failed due to the following
error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
I am aware that this is often due to incorrect registery keys, like here:
unable to cast COM object of type 'microsoft.Office.Interop.Excel.ApplicationClass' to 'microsoft.Office.Interop.Excel.Application'"
But I only have one registery key, removed it, and office itself put it back in it's place, so I guess it's the correct one.
Does anyone know how I can solve this?
I use Visual Studio 2015, and office 2013 Standard, in english.
Thank you in advance!
Apperantly I needed to use the type:
Microsoft.Office.Interop.Excel.Worksheet
Instead of
Microsoft.Office.Tools.Excel.Worksheet

Adding Excel Object Library conflicts between Excel.TextBox & Forms.TextBox in Office Development

I have implemented several basic Excel functions in my vb.net application (opening an xls workbook & accessing worksheet). However, it appears that when I add the Reference "Microsoft Excel 14.0 Object Library" the application is getting confused with the standard System.Windows.Forms objects and has the following error: InvalidCastException occured: Unable to cast object of type 'System.Windows.Forms.TextBox' to type 'Microsoft.Office.Interop.Excel.TextBox'. The Invalid Cast error is happening when calling a subroutine & passing the application form controls (check boxes, GridView, TextBox, etc) from my main "Form1" class into a UtilityFunction module. UtilityFunction has a reusable Windows Registry sub routine which retrieves/saves values at application startup/closing. This worked in the past, but now is crashing at the subroutine call in the Form1 class. The exception occurs during application runtime, not during the compile/build.
Also, I deleted the text controls from the form and created them manually, but I'm still getting the same exception error.
When you have a Namespace conflict you need to fully qualify the object you want.
Dim excelTb As New Microsoft.Office.Interop.Excel.TextBox
Dim formTb As New System.Windows.Forms.TextBox
I solved this problem by using the following code:
Imports X = Microsoft.Office.Interop.Excel
Dim xlApp As X.Application = New X.Application

Invalid Cast Exception when filling datatable wth table adaptor

I am using VB.NET 2010 (Visual Basic 2010 Express) on a WPF-based project. I am also using the SQL Server Express built-in to Visual Basic 2010 express.
I have just about finished refining my code for hooking up my wpf-based form to an existing SQL database (agentroster.sdf). I have a global data source (AGENT_ROSTER) connected to this database. Connections are confirmed to work properly.
This is the first part of the code I'm using, irrelevant code omitted,
Dim table_adaptor As New AGENT_ROSTERTableAdaptors.AGENT_ROSTERTableAdaptor
Dim roster_table As New DataTable("roster_table")
Dim rowposition As Integer
Private Sub ROSTER_Loaded...
table_adaptor.Fill(roster_table)
End Sub
I am getting the following errors:
(In Immediate Window)
A first chance exception of type 'System.InvalidCastException' occured in VBP-WORD4WORD.exe
(In Message, pointing to the line: "table_adaptor.Fill(roster_table)')
InvalidCastException was unhandled
Unable to cast object of type 'System.Data.DataTable' to type 'AGENT_ROSTERDataTable'.
What am I doing wrong, and furthermore, how do I fill roster_table with table_adaptor (or alternate method)?
Assuming that your strongly typed DataSet is called "AGENT_ROSTER":
Dim table_adaptor As New AGENT_ROSTERTableAdaptors.AGENT_ROSTERTableAdaptor
Dim roster_table As New AGENT_ROSTER.roster_table
table_adaptor.Fill(roster_table)
Have a look at Efficient Coding With Strongly Typed DataSets.