Forms and modules in VBA to be converted to C#


I'm starting to convert a number of "utilitarian apps" from Access/VBA to C#, and some of the equivalents escape me sofar.

By "utiltarian" I mean Access apps that run unattended, process data in various databases (mostly in one SQL Server DB), and possibly go through various phases of processing. So I have typically constructed them around one main form which when loaded calls a number of routines, some located in the form itself, and many located in modules, of which there are 2 categories: standard, generic modules which are used by many of the apps, and specific modules which do some specific processing only in one of the apps.

Many of my modules log what they are doing in a table in SQL Server, and they also add the same or similar kind of text log entries in one listbox on the main form, which always bear the same name, lbProgress, in all apps and which allows me when developing and testing to see what the code is doing and what problems it encounters. So basically I have this:
- main form calls subroutine A in module X by passing any needed arguments, but always Me as argument
- subroutine A (which has the argument "frm as Form" to map the Me argument in the sub call in the main form) starts working and, when it wants to "publish" the fact that it has reached some step in the processing, it calls a generic logging routine, passing it its own "frm" parameter and the text to log as arguments
- the generic logging routine uses these arguments to add the logging text to the main form's list box lbProgress by referring to it as frm.lbProgress

So in pseudo code, it is something like (simplified):

Private Sub Form_Load()  (of frmMain form)
    Call A(Me)
End Sub

in specific module of app:
public Sub A(frm as Form)
    ' Want to log text "Step 1 completed"
    call LogProgress(frm, "Step 1 completed")
End Sub

In generic module modAppLogging:
Public Sub LogProgress(frm as Form, sLogText as String)
    Dim Temp as Variant
    Temp = SysCmd(acSysCmdSetStatus, sLogText )
    frm.lbProgress.AddItem sLogtext
End Sub

I thought I would therefore start to rewrite such a generic module, which is basically a collection of public sub's doing some processing which may or may not access data in tables in a SQL Server DB, and to make a solution with one form as project and the generic module code in a sealed class. However, I'm stumbling on many small obstacles:
- the main form passes its reference "Me" in the sub call to A, because it might be used by A and by the LogProgress generic routine. What's the equivalent to "Me" in C# ? "this" ?
- is there an equivalent in C# for the SysCmd call, which just shows the log text in the status bar of the form ?
- the LogProgress routine uses in VBA the 2 arguments shown above: a reference to the main form, and a string. I can't fathom what type this "frm" variable should be in the sealed class A and in the sealed class where LogProgress is, i.e what's the type in:
public static void LogProgress( ??Type?? frm, string sLogText)

Thanks for helping me with these probably trivial problems.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Scott McDaniel (Microsoft Access MVP - EE MVE )Infotrakker SoftwareCommented:
.NET languages are a far cry from Access VBA. I don't use C#, and instead spend most of my time in VB.NET when I work in that environment, but the concepts are the same.

If you're running "service" type apps - i.e. apps that run unattended, with no user interaction - then in general there's no need to have any Form or UI conventions (except for setup and maintenance, perhaps). When the service app is running, there's just no need to show forms, or fill forms with data, etc etc, as we're accustomed to doing in Access, and doing so can run into unintended errors and such (or can allow users to interact with your service app, which is a bad thing in most cases). Instead you'd typically create Class modules that would interact with the database, and in those Class modules you'd include your various Subs and Functions.

As far as SysCmd - there is no equivalent in .NET. The SysCmd functions in Access basically just fired off internal System Commands. If you want to fill a Label in .NET, you just set the .Text property of that label directly:

lblInfo.Text = "Running Code A"

If you need to refer to a specific Form in your .NET application, you'd generally create that form using a Global variable, and then refer to that Global variable:

Dim frmMain As fMain

Now in the startup code for your project:

frmMain = New fMain

From there, you could refer to frmMain anywhere in the project:

frmMain.lblInfo.Text = "Something Here"

If you MUST have a form, then an even better solution would be to move all that code to a Class module, and then have that class fire off Events as needed to inform the interface of the progress, and your interface could react accordingly. You could then instantiate the Class in the Form's module using the WithEvents method, and all of the Events of that Class would be available for use with the Form. For example, if I have this event in my Class:

Event AlertUI

Then my Form's module would be able to fire off code anytime my Class module "fired" that event. So essentially, after moving your code into a Class module, you'd just call that Event as needed to alert the UI that something is going on, and the UI would then handle that event as needed - it could write to a Textbox, Label, StatusLabel, etc etc.

Note the above is VB.NET syntax, although C# would be similar.

In short, much of what you're trying to do attempts to force C# to act more "Access-like", and that'll get you in trouble quickly. I made the conversion from an Access-only programmer to .NET several years back, and I went through a period much like this - trying to force .NET to act like Access. It was difficult (to say the least) and in the end .NET won that battle :). I'd strongly suggest that you learn the C# (or VB.NET) language and adapt your code to that environment, rather than trying to cram VBA-centric code and processes into the wrong container. The .NET languages are much, much different from VBA, and from the Access data-centric paradigm.
käµfm³d 👽Commented:
By "utiltarian" I mean Access apps that run unattended, process data in various databases (mostly in one SQL Server DB), and possibly go through various phases of processing.
This sounds like it should be a console application, not a Forms application.

What's the equivalent to "Me" in C# ? "this" ?

If you need to refer to a specific Form in your .NET application, you'd generally create that form using a Global variable, and then refer to that Global variable:
I disagree with this. Creating globals is the old way of thinking. The preferred way is to pass around abstractions of your form by way of interfaces and abstract classes. But I won't subject you to that at this point in your learning  = )
Scott McDaniel (Microsoft Access MVP - EE MVE )Infotrakker SoftwareCommented:
kaufmed has much more experience in this, so I'd certainly defer to his judgement in this matter. My goal with the post was to try and pave something of a path from VBA to .NET (if such a thing exists, that is).
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

bthouinAuthor Commented:
Hi Scott

Yes, I know that such apps do not need a UI, but because they do sometimes complicated stuff, it's much nicer to follow what's happening in one single app on a form listbox being filled by the executing code than fishing with SQL queries in a huge table with logging entries from 10 different apps.

And yes I know I'm (unnecessarily) trying to mimic what happens in my Access apps, but I thought that would teach me at the same time a number of things which I'd need anyway later on, because I will have to convert also typical data manipulation apps used by people. And users would anyway not be able to (mis)use my service-type of apps, because they will run on servers on which they' have no access. All they'll ever see is the interactive apps they have today, just in another guise (Win Forms or web forms with ASP.Net).

I HAVE to use C#, I would have preferred VB 10 times over, but that was not for me to decide.

OK, thanks for your valuable inputs, I'll see how much and how fast I can "bend" my  Access habits into C#-conform habits :-)
käµfm³d 👽Commented:
All they'll ever see is the interactive apps they have today, just in another guise (Win Forms or web forms with ASP.Net).
You'll want to take an n-tiered approach to your development then. With such an approach, you will be able to easily swap out layers as you see fit. For example, if you made 3 tiers--a UI layer, a service (validation) layer, and a data layer--you could easily swap out the UI layer between WinForms and WebForms (or something else)--the only thing changing is the technology that is used to display the data.
bthouinAuthor Commented:
Hi kaufmed

Yep, that sounds good, and I'll do it in the end. My problem is that I have very little time to do the conversion (about a year to convert 30,000 lines of VBA code + forms, queries and a few reports) spread over 20+ Access apps, so maybe I'll do it 2-tier first to gain basic experience, and then improve afterwards when I get to the maintenance mode period. I know, it's nearly double work, but I hardly have any choice and too little know how to risk grand plans and perfect structures. The whole thing has been kicked off by guys making lots of politics, so there are loads of aspects which I have to consider which hamper a healthy development. And being a lone-ranger contractor, I cannot impose my views against IT departments with thousands of employees.
käµfm³d 👽Commented:
Understood. Honestly, making it 3-tier shouldn't be too complicated, and I would focus on what the code as a whole does, not what each line does.. You basically have:

One project for UI
One project for service layer
One layer for data access

You would have data transfer objects (DTOs--i.e. classes) that carry data between layers. Your UI layer will be dumb:  get some inputs; display some outputs. Your UI layer puts the inputs into a DTO that goes off to the service layer. The service layer runs its validations against the inputs to ensure that they are up to snuff. If they are not, return an error; otherwise, forward the DTO on to the data layer to execute the query/queries.

Ultimately, its your project, so do it the way that makes sense for you. Just giving my opinion  = )

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.