When is the VB.Net Replace function not Replace?

0
Filed under VB Feng Shui

I ran into a little surprise a few days ago. With something as innocuous as the “Replace” function, of all things!

Now, Replace has been around since, well, forever. The basic function has always looked like this:

X = Replace(StringToSearch, StringToSearchFor, StringToReplaceWith)

No big deal. Used it for years.

So imagine my surprise when I got an “Object not set” error on a string variable that I’d just used Replace on! How could that be?

So I checked the variable value. It was, in fact, “Nothing”.

Ok, So I rerun the code, stepping through. The variable starts out as a string containing some data, then gets trimmed, and the resulting string in empty (still a string, just containing no characters).

Then I perform a replace on it, and suddenly, the string is Nothing?!

So, I coded up the following little test snippet.

Private Sub Test() Dim x = "Test A B C" Debug.Print(Replace(x, "A", "Z")) 'Results in "Test Z B C" Debug.Print(x.Replace("A", "Z")) 'also results in "Test Z B C" x = "" x = x.Replace("A", "Z") Debug.Print(x Is Nothing) 'result is false, (x stays "") x = "" x = Microsoft.VisualBasic.Replace(x, "A", "Z") Debug.Print(x Is Nothing) 'result is true!?! x = "" x = Replace(x, "A", "Z") Debug.Print(x Is Nothing) 'Result is true!?! End Sub

The first two results are exactly as expected. The search string is replaced with the replace string.

The next result, ALSO, is as expected. x starts out as an empty string. I perform a replace on it, and the result is, duh! an empty string! Now, for as long as I’ve known the Replace function, this has not been how it works.

But the next two results both result in FALSE, meaning the result of the String.Replace function and of the Microsoft.VisualBasic.Replace function is Nothing, and not an empty string!

Google It!

So I started googling. I turned up this bug report from .net 1.1.

The response from Microsoft is:

Posted by Microsoft on 5/18/2006 at 3:02 PM
Hi,
Thank you very much for reporting this issue. Unfortunately, VB had this behavior in previous version too and we can’t change it due to backward compatibility problem.
Thanks,
VB Development Team.

“Can’t be!” I yelled. Well, ok, I didn’t yell, but I exclaimed heartily <g>.

So I fired up VB6 and wrote up another test program, then ran it.

You can see the VB supplied variable inspector tooltip as I hovered over the value of X after I’d just run the normal REPLACE function on it in the EXACT SAME WAY as I’m doing in VB.net.

image

I hate to burst bubbles, but X starts out as an empty string, I run the REPLACE function on it, and it ends up… wait for it… an empty string! Not a null/nothing variable.

Maybe it’s another weird edge case scenario that the VB Team is talking about there, but, come on! This has got to be THE SINGLE MOST COMMON invocation of Replace. Why on earth should it work differently from VB6 to VB.net?

And one other thing. String.Replace is part of the .net FRAMEWORK people. It has virtually nothing to do with VB6 and certainly, compatibility shouldn’t have been a concern there. May for the version in the VisualBasic namespace, but not that String.Replace. Weak!

Short version of the story

Be VERY CAREFUL of using either String.Replace or the Microsoft.VisualBasic.Replace functions.

If you DO need them (they have a nice case-insensitive switch, which makes them handy), write a wrapper function that deals with this VB.net bug (yeah, I went there <g>) so you won’t get bitten and end up with rash.

PicPick, A Great Little Freeware ScreenCapture Tool

0
Filed under Utilities

At my last job, we used Snagit exclusively for screen captures. It’s a great tool, but it’s a tad pricey for doing quick screenshots on your home machine.

Just today, I was at a new contract gig and needed to do some screenshots. There wasn’t anything decent already available so I went googling for a bit.

First up. I believe I’ve talked about Faststone Capture before and that’s one of the first hits I got. But after downloading the latest version, I discovered that they’ve gone to a paid version with a 30 day eval. Don’t get me wrong, Faststone is a good screen capture util, and you might want to give it a whirl, but in this case, I was looking for something small and free.

Next try. Struck Gold!

PicPick is a little freeware app from wiziple.net. Odd name, but for free, it’s one amazingly polished screen capture app.

image

Let’s see, what’s to love?

  • It’s got a built in image editor for quick annotations.
  • It can do full screen caps, region caps, window caps, freehand caps, you name it.
  • It’s fast.
  • It can save to several different image formats

and lastly…

It’s got a built in screen protractor! WTH!

image

If you need to do screencaps on a budget, definitely check this one out!

Visual Studio Styles Made Easy

0
Filed under .NET

Luke Sampson’s put up a nice little site that’s all about custom color styles for Visual Studio (looks like most schemes support VS2005/2008 AND 2010!)

For example, the high rated scheme right now is WekeRoad:

image

Pick one and you can download the scheme right there. Very easy to get a custom scheme (or a good base for your own scheme) going quickly.

I tend to prefer something with a few less colors (I’m not keen on the circus look, no matter how muted), but some of these schemes look quite nice.

Finally, check out my post about programming fonts here for a good font comparison.

XPath Testing Tool (XPathMania)

0
Filed under Utilities, VB Feng Shui, XML

I mentioned RAD Software’s RegularExpression Designer a few posts back, but this time, I’m talking XPath.

If you haven’t already played with XPath, and you do much of anything at all with XML data, you owe it to yourself to check it out. Basically, it’s a query language that allows you to query for specific nodes or nodesets from an XML data source very easily. It’s also got some limited function and expression handling capabilities (typical math functions, string manipulation functions, etc).

XPath 1.0 is fully supported by the .net framework. Unfortunately, XPath 2.0, while much more capable, has been dropped by Microsoft in favor of, I believe, XQuery. Trouble is, I can’t find much in the way of VB.net support for XQuery right off.

But, all that aside, XPath 1.0 is still very much a useful tool to have in your arsenal, but, like regular expressions, getting an XPath query right can take some experimenting. That’s where XPathMania comes in.

It’s basically an XPath query tool extension to the VS 2008 IDE.

In the screenshot below, you can see that I’ve got an XML file loaded, and I’ve docked the XPathMania window just below it.

With that, I can easily enter a query again that XML file and view the results (along with the matching nodes actually highlighted in the XML file view! Good stuff!

image

Finally, you’ll also definitely want to check out this page for lots of good XPath example queries.

In the future, I’ll try to put together a little sample app that illustrates how to use the XPathNavigator to easily execute these queries against an XML document and enumerate the resulting nodeset.

FreeCommander Ain’t Half Bad

0
Filed under Utilities

The other day, I was needing to quickly view lots of log files in a folder. The Ol’ “Double click/open in notepad/close notepad/arrow down/repeat” process was getting old quick.

Now, at home, I’ve got Directory Opus, which would make this a breeze. But, it’s a licensed copy, and unfortunately, their licensing is a tad draconian. Besides, I was at an office, so I didn’t have my sernum or anything like that handy.

So, I started poking around. I’d looked at a pile of Explorer replacements awhile back. That’s how I ended up buying DirOpus. But this time, I needed something free I could download, install and get my job done.

A few minutes of googling pointed my to FreeCommander. I can’t say I even looked at this package before, because it’s billed as a “Norton Commander Clone”, and I never really got into Norton Commander.

image

That picture viewer you see on the right? It’ll view just about any file type, which was just what I was needing.

But come to find out, FreeCommander is much more than just a Norton Commander clone.

There’s lots of very cool features here, including:

  • Tabbed explorers
  • A decent Tree (it doesn’t show the full tree like explorer does, but it comes close enough to be useful)
  • A decent file viewer that can be “in place”, meaning it doesn’t open a new window to show the file being viewed.
  • A “Quick Filter” which is very handy.
  • Predefined Filters, for when the quick filter isn’t quite enough.
  • Lots of config options
  • Reasonably fast, even in dirs with lots of files.

And finally, so far, it’s been very stable.

In all, a very compelling Explorer replacement, especially considering the price!

OpenGL 2.1 on an ATI Radeon x1900XT

2
Filed under Arcade, Hardware

I converted my system over to Win7 64 about 5 months ago, but hadn’t really had much time to do any gaming.

Eventually, my daughter asked about playing a Disney Princess CD that she’d played for months under Vista 32.

So I pulled out the CD, ran through the install and started it up. Chug… Chug… Chug… Crash!

Ugh. This isn’t good. After some digging around, turns out that Disney Princesses is an OpenGL game that requires 1.1+. Ok fair enough. This is Win7 after all.

I found an app called OpenGL Extensions which shows detailed info about the OpenGL stack loaded and turns out, I was using the generic MS video driver and OpenGL 1.0. Yikes!.

So I tried installing the latest ATI drivers, which, as of April 2010, is 10.3. No dice. The x1900XT is no longer supported.

Double Yikes!

And this card is not  that old.

Long story short. I grabbed the 9.11 version of the Catalyst drivers off the ATI website here. They appear to be the last version (for Vista 64) that did support the x1900XT, and they DO install under Win7 64 (albeit the manager pops an error about some MOM file being missing, but that doesn’t seem to affect the drivers).

Now, OpenGL extensions reports OpenGL 2.1 and that game works flawlessly.

And, I suppose, I’ll be in the market for a newer video card at some point in the nearish future.

Parsing Key-Value Pairs Via Regular Expressions

0
Filed under Code Garage, Regular Expressions, VB Feng Shui

I’ve often found myself in need of a Key-Value pair parser. Simple stuff, really. Essentially, the idea is to be able to parse any of the following from a typical command buffer:

Key=Value (no whitespace in the key or value)

Key=”Value” (whitespace is ok in the value)

Key (when just the existence of the key signals something)

This sort of parser is fairly easy to write, but this time, I’d just finished playing with regular expressions for another parsing task, so I thought, why not give them a try here?

After a few minutes with the Rad Regular Expression Designer, I’d put together what appeared to be a pretty robust expression for this.

My version keys of the matches instead of the seperators. I did this mainly because I wanted the Key and Value parts to be returned as “cleanly” as possible. That means the Key should be just the Key, no whitespace or “=” and the value should never include the leading or trailing quote marks, if they’re there).

The end result is a function that takes a string buffer and returns a generic Dictionary of Key Value string pairs.

Imports System.Text.RegularExpressions


Module RegEx

    Public Function ParseKeyValuePairs(ByVal Buffer As String) As Dictionary(Of String, String)
        Dim Result = New Dictionary(Of String, String)

        '---- There are 3 sub patterns contained here, seperated at the | characters
        '     The first retrieves name="value", honoring doubled inner quotes
        '     The second retrieves name=value where value can't contain spaces
        '     The third retrieves name alone, where there is no "=value" part (ie a "flag" key
        '        where simply its existance has meaning
        Dim Pattern = "(?:(?<key>\w+)\s*\=\s*""(?<value>[^""]*(?:""""[^""]*)*)"") | " & _
                      "(?:(?<key>\w+)\s*\=\s*(?<value>[^""\s]*)) | " & _
                      "(?:(?<key>\w+)\s*)"
        Dim r = New System.Text.RegularExpressions.Regex(Pattern, RegexOptions.IgnorePatternWhitespace)

        '---- parse the matches
        Dim m As System.Text.RegularExpressions.MatchCollection = r.Matches(Buffer)

        '---- break the matches up into Key value pairs in the return dictionary
        For Each Match As System.Text.RegularExpressions.Match In m
            Result.Add(Match.Groups("key").Value, Match.Groups("value").Value)
        Next
        Return Result
    End Function


    Public Sub Test()
        Dim s = "Key1=Value Key2=""My Value here"" Key3=Test Key4 Key5"
        Dim r = ParseKeyValuePairs(s)
        For Each i In r
            Debug.Print(i.Key & "=" & i.Value)
        Next
    End Sub
End Module

I’ve included a simple test function to help validate it.

DISCLAIMER: I’m not RegEx guru, so there are likely much faster ways to assemble the Regex. If you have one, by all means please comment! And finally, it’s entirely possible that I’ve missed some examples of badly formed input that would cause weird parsing results.

For instance, in the above example, notice that “Key3=Test Key4 Key5” will return Key3 set to “Test” and Key4 and Key5 set to empty strings.

If the user meant for Key3’s value to be “Test Key4 Key5”, there would need to be quotes around the value.

But, parsing issues like that will be the norm in any kind of parsing logic for formats such as this, so I’m not terribly worried about it.

Implicit Casts in VB.net

0
Filed under Code Garage, VB Feng Shui

I really hadn’t paid much attention to Implicit Casting in VB. I’d heard the term, thought it might be an interesting idea, but then completely forgot about it.

But I was recently reading a blog post discussing the EntitySpaces ORM, and the author happened to offhandedly mentioned implicit casts with respect to certain features of that ORM. I was intrigued again, so I set off down that road.

Come to find out, Implicit casts were one of the language features new in VS2005! (wow, how’d I miss that?) Essentially, they allow you to explicitly dictate what happens when you implicitly  cast one object to a different type.

How’s that again?

VB is rife with instances where you might need to implicitly cast one object to another of a different type. You’ve got the obvious situations, for instance, converting an object from a subtype to a super type (granted, not the most ideal example, but it illustrates the point):

Dim d = New Dog
Dim a As Animal = d

And then there are more subtle examples. Here, I’ve created a Dog object with the name “Rover” but then I’m comparing it directly to a string. The implicit conversion is from Dog to String:

Dim d = New Dog
d.Name = “Rover”

If d = "Rover" Then blah....

Now, before anyone rails on me for encouraging bad programming practices, these are all contrived examples, just to point out the possibilities.

The point is, if you find yourself needing to cast one object into another, and such casting makes logical sense, implicit casting provides a very clean, terse way to accomplish it.

Widening or Narrowing?

Any time you convert one object to another, there’s only 2 possible outcomes:

  • The conversion will always succeed. This is known as a Widening Conversion.
  • The conversion could succeed or fail. This is known as a Narrowing Conversion.

A lot of documentation on the matter will describe a Widening Conversion as one that converts a derived type to one of it’s base types, and a Narrowing Conversion as one that converts a base type to a derived type, but in practice, the two types don’t have to be related at all.

For instance, you can define either a Narrowing or a Widening conversion operator to convert from a StringBuilder Class to a String and vice versa, but neither type is directly related to the other.

The Caveats

There’s always at least one, right? Well, first, as you might guess, used with abandon, implicit casting can lead to code that bears a striking (and quite unwelcome) resemblance to old school VB code chock full of variants.

But a less obvious snag is that when you cast, you need to pay special attention to whether you’re creating a new object or just recasting the existing object.

For instance, you might define a Widening Conversion from Dog to Animal as:

Public Shared Widening Operator CType(ByVal InitialData As Dog) As Animal
    Dim a = New Animal
    a.Name = InitialData.Name
    Return a
End Operator

But in actuality, a new Animal object with the same Name as the original Dog object is created. That might be what you want, or it might not be.

Project Level Implicit Conversion

If you’ve never noticed before, your project actually has an overall level of warning configuration for Implicit Conversion, because it can be such a nasty issue.

You’ll find it on the Compile Tab of the project properties:

image

  1. Set to None, VB won’t warn you at all when you attempt to implicitly convert types.
  2. Set to Warning, VB will show a warning in the Errors list, but will still allow the project to compile.
  3. Set to Error, VB won’t even allow the project to compile.

Generally, you’ll want this set to Error. The good news, however, is that even with this option set to Error, VB will not consider those implicit conversions that are handled explicitly by a Widening Conversion as errors. If you think about it, this makes sense, because a Widening conversion, by its very nature, can’t fail, and thus really isn’t an implicit conversion anymore.

StringBuilder Example

Francesco Balena wrote up an excellent short article here that illustrates using a Widening conversion to make working with StringBuilder objects far easier. He uses Widening conversions to implicitly cast from StringBuilder to String and back, like so:

Public Shared Widening Operator CType(ByVal op As StringBuilder6) As String Return op.ToString() End Operator Public Shared Widening Operator CType(ByVal str As String) As StringBuilder6 Dim op As New StringBuilder6() op.buffer.Append(str) Return op End Operator

Since these are Widening Conversions, they won’t fail, and thus they won’t be flagged as errors even with Implicit Conversions set to Error in the project properties.

A One Line CSV Parser

0
Filed under Code Garage, Regular Expressions, Utilities, VB Feng Shui

Parsing up Quote Comma delimited text is a pretty common thing to do, and it seems trivial enough till you realize all the little gotcha’s that come with the problem (like doubled quotes, commas in quotes, etc, etc). Then it becomes just another laborious exercise in boring coding.

I came across a regex some time ago that makes the process literally one line of code. I can no longer find the original author but the code I found (what little there was of it) was C# and actually split up into a few lines of code, so this is converted to the equivalent VB.net:

    Public Function QCSplit(ByVal Args As String) As String()

        Return (New System.Text.RegularExpressions.Regex(",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))")).Split(args)
    End Function

The regex used here doesn’t actually match on the contents, it matches on the commas that split things up, and it then uses the SPLIT function to actually split those things up.

I’ve used this a while now and it works great, but I’ve seen a few interesting alternatives since.

The most interesting thus far is this one by Daniel Einspanjer. Not interesting enough yet for me to switch to it, but the regexlib.com website is quite nice as a great repository of good regex recipes.

Regular Expression Tester

And speaking of Regular Expressions, the guys over at RAD Software, have a free Regular expression tester for .net style regular expressions that works fantastically. If you’re just starting out in regex’s (and seriously, who isn’t <G>), you owe it to yourself to pick up a decent regex test tool, and this one is as good as I’ve seen so far.

image

As far as I can tell, it can handle all the various options for regex’s, and dynamically shows match results, etc. Very handy for trying out expressions without actually running them in .net.

Add it to your External Tools menu in VS and it’ll be right there, good to go.

Mail Merge and Reports in Word

2
Filed under Office, VB Feng Shui

If you have a need to generate documents, and I mean lots of documents, you’re likely the eventually investigate the Word mail merge functionality.

It’s ok, but there’s lots of things that it can’t do, especially with respect to generating tables or dealing with table oriented data.

You next stop might be a report generator, like Crystal Reports. But the big problem with those kinds of packages is they require you to use a proprietary report template editor, usually band oriented (the typical “header/body with repeating lines/footer” type reporting system). Not terribly bad, but not great if you actually want to generate mail merged documents.

Word Documents as Templates

But there are alternatives out there. Two of the most intriguing I’ve seen are an open source package called FlexDoc and a commercial application called Windward Reports.

Both of them allow you to use standard Word documents as “report” templates”. But keep in mind, “report template” in this sense is a pretty open ended concept. You could generate everything from a mass mailing letter, to legal documents, to actual reports with tabular data, and even graphs and charts.

And both are lightning fast, since they work directly on the Word document file itself (or more precisely, the DOCX file format, older DOC format files aren’t supported).

The Commercial Product

Windward Reports is polished commercial product. It’s not cheap, but it’s incredibly flexible, supporting everything from XML to SQL data sources, charting, graphs, tabular report type elements, formatted content (ie insert a field into your Word document that consists of formatted HTML, for example), and a lot more.

Windward uses standard Word Mail Merge fields for its tags, specifically the AUTOTEXTLIST field. Those field types have been in Word since even before Word 2000, and it’s very unlikely they’ll change any time soon, so you’re pretty safe there.

One really nice element of Windward is that they have available a “tagging helper” addin for Word called AutoTag. It can really help speed up the design of your Word report templates. It’s optional. Technically, you don’t absolutely have to have it, but it’s a lot more painful to create reports without it.

The Open Source Project

Flexdoc is open source and not quite as polished as Windward. But it’s got much of the same functionality. It can connect to just about any data source, it’s fast, and it can do tabular data very well, but it can’t do charts or graphs, and it can’t handle formatted data (hmtl or otherwise) at all by default, though there are mods that can be made to improve that situation.

The biggest problem with Flexdoc is that it currently relies on the CustomXMLElements functionality of Word that has, as of Jan 10, 2010, been removed from the product because of the lawsuit with I4I.

The author of FlexDoc indicated that there were plans for a ContentControl-based version in the future, but that might be a while off. Still, it’s an open source project, so you could always throw in and help make those changes if you really needed them.