# Option Strict On disallows late binding



## leonlai (May 15, 2019)

Hi, everybody

I am not sure this is the correct forum to ask my question. But any help can orient me towards the solution.

I am developing a VB.NET Sub which can get data from SQL Server to my Excel Sheet at lightning speed (using ADODB connection).

My Sub is written in VB.NET, not VBA. But I verified that it also works in VBA.

Here is my code:


```
Option Strict On
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.ComponentModel
Imports AddinExpress.MSO
Imports System.Data.SqlClient
Imports System.Data
Imports System.Data.DataSet
```


```
Private Sub AdxRibbonButton1_*******(ByVal sender As System.Object, ByVal control As AddinExpress.MSO.IRibbonControl, ByVal pressed As System.Boolean) Handles AdxRibbonButton1.*******


        Dim Conn As New ADODB.Connection
        Dim recset As New ADODB.Recordset
        Dim sqlQry As String, sConnect As String
        Dim xlWb As Excel._Workbook
        Dim xlWsht As Excel.Worksheet = TryCast(ExcelApp.ActiveSheet, Excel.Worksheet)

        xlWsht.Cells.ClearContents()

        sqlQry = "EXECUTE[dbo].[MyStoredProcedure]"

        sConnect = "Driver=SQL Server;Server=MyServer; Database=MyDatabase; User Id = sa; Password= 12345"

        Conn.Open(sConnect)
        recset = New ADODB.Recordset

        recset.Open(sqlQry, Conn)

        Dim icols As Integer
        For iCols = 0 To recset.Fields.Count - 1

 '//------------ MY PROBLEM IS HERE --------------------------------
            xlWsht.Cells(1, icols + 1).value = recset.Fields(icols).Name

'// -----------------------------------------------------------------------
        Next
            
       
        xlWsht.Range("A2").CopyFromRecordset(recset)

        recset.Close()

        Conn.Close()
        recset = Nothing

    End Sub
```



*MY PROBLEM*

My code works perfectly if I set _Option Strict OFF._

But if I set _Option Strict On_, there is an error at this line:

```
xlWsht.Cells(1, icols + 1).value = recset.Fields(icols).Name
```

_Info: This line of code adds the headers which are missing because "CopyFromRecordset" does not copy headers._

The error Message is:


> Option Strict On disallows late binding




Can anybody help me write the above line correctly?

Thanks
Leon


----------



## leonlai (May 15, 2019)

Hi, everybody

I am working hard on my problem.

I found that the following codes work perfectly, and produce the expected results:



```
xlWsht.Range("A1").Value = recset.Fields(1).Name
xlWsht.Range("B1").Value = recset.Fields(2).Name
xlWsht.Range("C1").Value = recset.Fields(3).Name
xlWsht.Range("D1").Value = recset.Fields(4).Name
xlWsht.Range("E1").Value = recset.Fields(5).Name
xlWsht.Range("F1").Value = recset.Fields(6).Name
xlWsht.Range("G1").Value = recset.Fields(7).Name
```

But I want to parametrize the codes.
As I mentioned, I tried:


```
For iCols = 0 To recset.Fields.Count -1
     xlWsht.Cells(1, iCols +1).Value = recset.Fields(iCols).Name
Next
```

It is this code which does not work and that I need to correct. 

Now that I have simplified my problem, I hope someone will reply. 

Thanks
Leon


----------



## Norie (May 15, 2019)

Leon

Which part of the code isn't working?


Is it *xlWsht.Cells(1, iCols +1).Value* ?

Is it  *recset.Fields(iCols).Name* ?


----------



## xenou (May 15, 2019)

It is possible that using the Excel model in VB.NET does not give you access to ranges through a Cells() reference.  Also in keeping with the general syntax of VB.NET, it is also likely that you should be using brackets, not parenthesis.

So you can try:
xlWsht.Cells[1, iCols +1].Value = recset.Fields[iCols].Name

Or otherwise keep trying other experiments. Do not assume that VBA and VB.NET are the same - they are quite different. You have to search for examples of programming Excel with VB.NET, not with VBA.  For what it's worth, I prefer to use a more lightweight way of interacting with Excel spreadsheets in .NET. So for, instance, I would use something like EPPlus (https://github.com/JanKallman/EPPlus).  Basically, you don't need full-blown excel to create simple spreadsheets.  But anyway, that's my two pennies.


----------



## leonlai (May 16, 2019)

Hi, Norie

Thanks for your reply.

It is *xlWsht.Cells(1, iCols +1).Value *which is highlighted as error if I set Option Strict on:
" Option Strict on disallows late binding"

Please note that if I set _Option Strict Off_, the program works perfectly.
However, I do not want to Set Option Strict Off. I will go crazy if I do.

Best Regards,
Leon


----------



## leonlai (May 16, 2019)

Hi, xenou

Thanks for your reply.



> Do not assume that VBA and VB.NET are the same.



Yes, they are not exactly the same. But often, VBA can be converted to VB.NET with only some slight changes.
I use this approach, because it is easier to develop solutions in, and get help on VBA.
For example, the code which I have posted was originally written in VBA, and I found it works well with VB.NET.
The only problem is the one I raised.

I never heard about_ EPPPlus_. Thanks for sharing the tip. I'll see if I can use it.

Best Regards,
Leon


----------



## xenou (May 16, 2019)

Okay. Well, in this case this is one of the differences. You will have to use an explicit type (no late binding) or go with option strict off.
https://docs.microsoft.com/en-us/dotnet/visual-basic/misc/bc30574


----------



## leonlai (May 17, 2019)

Hi, everybody

Thanks to everybody who replied.

I am closing this thread.

Leon


----------



## Norie (May 17, 2019)

Leon

Did you find a solution?

If you did can you share it?


----------



## leonlai (May 20, 2019)

Hi, Nori

The lines which gave me a headache for 3 days and nights should be written like this:


```
'// COPY HEADERS FROM RECORDSET
For icols = 0 To recset.Fields.Count - 1
     TryCast(ActivShtCels(1, icols + 1), Excel.Range).Value = recset.Fields.Item(icols).Name
Next
```

With this correction, the code works perfectly, and I think I've got the fastest possible way to retrieve data from SQL Server. It retrieved 5000 rows from my Stored Procedure, just 2 seconds after pressing my button!

And the nice thing is it is a _disconnected_ model (does not block traffic) and the _recordset_ can be deleted asap (releases memory)!

The code is not mine, but copied from the foll. sites and amended to suit my requirements:

To retrieve the data (without headers) from SQL Server:
http://excelerator.solutions/2017/08/07/3-ways-perform-excel-sql-query/

To copy the (missing) headers:
https://docs.microsoft.com/en-us/office/vba/api/excel.range.copyfromrecordset

However, please note that I am not using VBA, but VB .NET in Visual Studio.
I often ask questions on VBA Forums as a first step, and then modify the solutions slightly to suit VB. NET.

However, the solutions presented in the 2 above sites work perfectly with VBA. Same lightning speed! I am amazed! No looping! Just _CopyfromRecordset _(unfortunately, it doesn't copy the headers).

Keep posting!

Best Regards,
Leon


----------

