VB.NET combobox persistence? - vb.net

I'm fairly new to VB.NET, and I've mainly been doing ASP programming up 'til now, and I have a pretty simple question.
I'm creating a program that will copy a selected file to a selected directory, and I want to store recent files/dirs so that they can be selected from a combo box. I was planning to just create a settings with "files" and "dirs", and just store the strings as | separated values (since that's an illegal file character).
Is there anything wrong with this approach, or are there any better methods?

I think your approach is fine as it seems to be simply a local cache of recent directories. You can persist the data in the application at the module level(create a module with a public object essentially is a global variable) but it goes away when the application is terminated.
This article is using a similar approach to what you were thinking although the example is in C#

Related

VB.NET Localization of strings

I've been successful in using form.location.resx files to localize the strings associated with form controls. However, I don't see how to (safely!) add strings to the .resx file(s) and then access them for such things as message boxes.
If I try to add a string to the .resx file using Visual Studio (2017), I get a warning dialog pop-up telling me that this could corrupt the "project item" (form) or my changes could be lost if I change the associated form.
Also, if I use this method, would I need to manually add my strings to each language file separately?
Alternatively, I could create a bunch of Labels to the form with visible=false and then edit their strings in the .resx files and use something like:
msgbox(LabelSampleMessage.text,MsgBoxStyle.Information,LabelSampleMessage2.text)
But that seems like it would be massively inefficient.
For Windows Forms, the best way to do this is to go into the Designer and set the Language property on the form. This will create a formName.Designer.languagecode.resx file for you. Then you just edit the Text properties of the controls. The changes will go to the resx file for the language you're editing. You can even have different layout and control spacing for each language (useful if a label is short in English but translates to something long in German).
For MessageBox messages, you do the same thing with the Resources.resx file. Just put all the messages in your Resources and duplicate the resx file for each language. Then use the Resource editor to translate the message in the other languages. You can then look up the message using My.Resources.Default.SomeMessageKey
#David: Note that I'm the author of a commercial ".resx" localization program for VS (in the interest of full disclosure). Yes, dwilliss is correct, though the names he used are a little off. For Windows forms, you can't manually update the ".resx" files yourself (directly), hence the warning from VS (don't know why they did things this way - go figure). You won't get that warning for strings you put in "Resources.resx" however. Just manually add "Resources.[LangCode].resx" and update it on your own. You have to add the keys yourself (again, no warnings). You can then simply access each string via the static properties seen in the "code-behind" file "Resources.Designer.cs" (one static property exists for each string you add). These are what MSFT calls "strongly typed" resources. If you access, say, "YourApp.Properties.Resources.SomeMessage" for instance (from "Resources.Designer.cs"), it will be returned in whatever language is currently set in "System.Threading.Thread.CurrentThread.CurrentUICulture" (assuming that language's satellite assembly is installed of course). This is all a pain and highly error-prone for other reasons as well, hence the reason I wrote my program (shameless plug but MSFT's way does work, though it's very primitive for handling translation in general - a professional organization relying on an external translator will save a lot of problems and $ in the long run by using a 3rd-party translation program, not mine necessarily though it would be my tool of choice of course, but anything is better than handling it manually).

VBA external modules

Is it possible to have modules be external to the actual Excel file and call the functions/subs within them externally?
My thinking is if there are multiple Excel files that use the same module, instead of updating each one of those files separately when I make a change, can I just update the one module stored on a server or something?
I have doing something like you describe for years. You can move your VBA code to a VB6 ActiveX dll, organize it into classes, and load that dll as a reference from Excel VBA.
This is a good way to reuse non-workbook specific code. For instance, I have code that queries a mainframe. I like to call it from Excel, but the details of the connection and how data is passed are contained in a dll that I can load from Excel, VB6, Word, .NET, wherever. I have a similar dll for reading data from AutoCAD drawings, one for interfacing with a product DB on a MySQL server, etc.
The code that remains in Excel tends to be simple formatting stuff. Say I return a variant array of strings (technically a COM SAFEARRAY) from some library that I wrote. I would then output it into Excel, maybe do a text-to-columns, and have a list of results returned to the user.
You can also pass and return more complex data structures. The beauty of VB6/COM Automation (and I didn't appreciate this until I learned to do it the harder way in VB.NET or C#) is that the data will flow in and out of your components seamlessly and all the necessary interfaces will be created for you.
The main change to your code will be replacing things like ThisWorkbook or ActiveSheet with explicit parameters like (Byval sht as Excel.Worksheet). These will be caught at compile time in VB6 (since it doesn't know what ThisWorkbook is), so you cannot overlook them; you are forced to pass an explicit reference.
I also notice that my code inside the dll becomes more paranoid if it receives a Worksheet or other Excel object as a parameter. In VBA you might have had more assurance that you were passing a good object since it was private to a given workbook. The dll does not know who is calling it, so I view the passed-in object with more suspicion (check if Nothing, sheet name, formatting clues to ensure I am using what I think I am using).
The only downside I see is that you will have to get a copy of Visual Basic 6.0. I bought mine in 1998. It is no longer available from Microsoft, but surely there is someone out there who will sell it to you. The latest service pack is SP6.
You will also have to become familiar with "regsvr32" and "regsvr32 /u" to deal with the "ActiveX can't create component" errors as you open your workbooks on various computers. I just publish my dlls to a mapped network drive and re-register them on the user's computers whenever there is a significant change. Obviously this is a intranet/single company solution. Publishing the updated versions is much more of a pain the farther you are distributed.
Not sure if this would satisfy your needs, but you could create your common module as an "add-in" and so install it so that all files that you open in the same instance of excel would have access to the add-in code.
It would not be my recommended way of doing it because I would be worried about suitable testing of all the excel files that use it, when you make a change, plus the added complexity of getting users to install your add-in (this may not be an issue for you). I have a "developersToolkit" module I use across 8 different Workbooks, but I import the module into each workbook so its stand alone and I can also test changes for compatibility with each of the 8 workbooks.

Is there a Cut & Paste as New Class File (Macro)?

I'm looking for a free Visual Studio feature, extension or macro. that can help with the following situation.
When I prototype I tend to keep all my classes in one file (bad practice I know, but yeah it a prototype). Then comes the point the where the files is too hard to navigate. So I breakout the classes into separate files inside the project, the folder structure reflecting the namespaces.
To achieve the is;-
1. Add new Folder
2. Add new Class
3. Name class
4. Cut and paste corresponding section into new class file.
For me, Steps 2 through 4 are prime fodder for a new Menu entries.
Cut Class as New Class File
Cut as New Partial Class File.
I've seen this feature in C# but not VB.net.
So does know any how to achieve this for VB.net?
Here's a macro that does what you want in C#... looking at the code it's probably fairly straight forward to modify it to work in VB...
http://plisky.net/main/macros/documentation
Also, I'm pretty sure all the commercial refactoring tools (Resharper, CodeRush, etc.) support this...
Resharper can do this using Move Type to Another File or Namespace
I just stumbled across this and can point you to an updated version of the macro that scrappy kindly linked. Its at http://plisky.net/main/plisy.net-visual-studio-productivity-macros.
If you still want it and wish to test it for VB I can happily make the changes to support VB.net but as I don't use VB I'd need a tester :) As its a while since this post you probably have something working already though.

using my own config file in my application

As a practice exercise at my college we have to make a simple room booking system, complete with its own config file. We're not allowed to use the one built into VB.NET (the professor wants us to adapt to not relying on things like that) so I've made my own. This is a sample:
// Config file.
// First column is the variable name that will be used to
// reference the value in the second column. Seperate each
// setting with a new line.
MasterUser Chris
DatabasePath C:\Users\Chris\Desktop\Project.mdb
Comments in the file are pretty self-explanatory. I can parse the file fine, but what I'm having trouble with is making a variable the same name as whats in the first column. For example I need to make a variable called MasterUser and one called DatabasePath that holds Chris and C:\Users\Chris\Desktop\Project.mdb as values respectively. But I have no idea how to make a variable called that.
Any help would be cool, thanks. :)
EDIT: You can't see it from the code view here, but the variable name and value in the config file are separated by a tab :)
You might want to consider using a better format for your configuration file, like XML. This will give you a lot more library support for parsing and searching within the file... that said, in this simple case, it looks like you just need a simple Dictionary(Of String, String) which probably won't make a lot of sense if you haven't learned about Generics yet :)
Basically you can load values in like this:
Dim settings As New Dictionary(Of String, String)
settings.Add("MasterUser", "Chris")
settings.Add("DatabasePath", "C:\Users\Chris\Desktop\Project.mdb")
Then when you want to retrieve a value based on the key in the dictionary, you can do it like this:
Dim master As String = settings("MasterUser") ' master = "Chris"
I hope that helps clear things up.
Well, in the strict sense, you cannot "Make a variable named from file data" in most compiled languages. What you could do is to make a name-value association set (that's a Dictionary in .Net) and add entries to it based on what you read from a file.
However, what most programmers do is to "invert" that logic: as you code reads each line, it just does a series of IF's on the Name to see if it is recognized, and if so then just assings it to the corresponding predefined variable of the same name.
There are formats & libraries specially made for this (like XML, that's why the built in configs use it), but that might still be the kind of thing that you are not supposed to rely on.
Since your configuration file is not compiled into your code in any meaningful way, you aren't going to be able to create a variable (that is, a strongly-typed property or field on a class) dynamically. You have a couple of options.
If you want to keep your configuration file format:
Create a class that contains all possible configuration keys as properties. Give that class a Load() method that knows how to parse a file into the class.
Use a Dictionary -- either the Generics version or good old fashioned System.Collections.Dictionary. You'll retrieve elements with string keys.
If you're willing to change your configuration file format to XML, then you can use Serialization. This frees you from having to maintain a parser, but it requires a little bit more setup.
See here for my answer to another SO's question using nini and where to download it from. Essentially nini is a simple INI read/write library for configuration files. The question that remains to be seen is will your professor allow this inclusion of 3rd party open source?
Hope this helps,
Best regards,
Tom.

Include sql scripts in a VB6 application

I am maintaining an old VB6 application, and would like to include SQL scripts directly in part of the project. The VB6 application should then extract the text of this script and execute it on the server.
The reasons for this approach are various - among others, we want to deliver only an updated executable rather than a complete update/installation package. Hence, the SQL scripts need to be compiled into the application just like a resource file. And, obviously, one has to be able to get at the content from code, in order to send it to the database server.
Does anyone have a good way to do this?
The simplest solution is to just create a VB module with the scripts as strings.
If you want to use a resource file instead, you can do that too. You can associate a resfile with a VB project (I don't remember how to do this directly in the VB IDE but the VBP file supports a ResFile32 parameter).
EDIT: It seems like the issue here is mostly about formatting -- you don't want to store SQL queries as one long string, but formatting the query nicely inside VB is tedious because you have to add quotes, add string concatenation operators to join the lines together, etc.
I would recommend placing the SQL in a text file and formatting it in whatever way you like. Write a script that will take the text and convert it into a VB module. The build process would be modified to always apply this script first before compiling the application.
For scripting, use your favorite scripting language; if you don't have a favorite scripting language, this is an easy enough task that you could do it in VB, C#, or any other language. If it were me, I'd probably use awk (gawk) or Python.
If you want to use a resource (.RES) to store your SQL, go to the menu:
Add-ins > Add-in Manager...
and select VB 6 Resource Editor. Configure the add-in to be loaded and to load at startup.
From the editor add-in, VB provides a simple interface to add resource strings. You will refer to these using the provided constant values. To load the strings at runtime, use the LoadResString function:
Public Const SQL_INSERT As Integer = 101
Dim strSQL As String
strSQL = LoadResString(SQL_INSERT)
(replace "101" with the constant value of the string you wish to load)
Just another thought on your approach. Because I find myself tweaking the program's behavior or UI for customers I might be in the middle of a change that either is not ready or has not yet been tested and approved. So if I have properties that change from time to time, but I want to maintain control of, for instance connection settings to our ftp server, I will create a resource only dll exposing my properties and use a resource file in the dll to supply the values. When my network manager changes something on the ftp server I change the strings in the resource maanger, recompile the dll and release just the updated dll. I'm sure there are many more solutions, but that is how I do it. If you don't think you might have to change your SQL scripts at the same time you are changing you exe this probably only complicates your work. It has worked well enough for me that now this is pretty much standard for me.