Calculated fields in CAML

So you have a SharePoint list with a calculated field. You want to select items based on the calculated field beginning with some specific substring. You write a CAML query:

<Where>
  <BeginsWith>
     <FieldRef Name="SortDate" />
     <Value Type="Calculated">200509</Value>
  </BeginsWith>
</Where>

This won’t work. (At least on my server) you’d always get informed that ” The SQL Server might not be started” + get a useless COM exception number 0x81020024. You can work around the problem by changing the value type to “Text”

<Where>
  <BeginsWith>
     <FieldRef Name="SortDate" />
     <Value Type="Text">200509</Value>
  </BeginsWith>
</Where>

This also works on the “Contains” operator. Other operators such as LessThan, GreaterThan, Equals, IsNull allow you to set the real value type – Calculated. Don’t know why. Probably a bug in Sharepoint.

Month names. i18n, you know

Whenever you see something like this you should come to an idea something is wrong (for instance, the guy who wrote this is still alive):

'month names in Latvian
Dim sMonth() As String = _
            {"Janvāris", "Februāris", "Marts", "Aprīlis", _
            "Maijs", "Jūnijs", "Jūlijs", "Augusts", _
            "Septembris", "Oktobris", "Novembris", "Decembris"}

Dim oListItem as ListItem
For iMonth as Integer = 1 To 12
  oListItem = New ListItem(sMonth(iMonth-1),  iMonth.ToString())
  Me.lstYears.Items.Add(oListItem)
Next

Explanation – if MS Windows knows quite well how months are named in Latvia, why should you try to be smarter than the big brother? Another explanation – if this is a web project (and in my case it is), you should think of internationalization whenever possible.

So a more correct way to add month names to a dropdown menu is:

Imports System.Globalization
....
Dim oListItem as ListItem
For iMonth As Integer = 0 To 11
   oEntry = New Web.UI.WebControls.ListItem( _
         CultureInfo.CurrentUICulture.DateTimeFormat.MonthNames(iMonth), _
            iMonth.ToString)
   Me.lstMonths.Items.Add(oEntry)
Next

And, to be even more precise, you could first check how many months there are in the current culture:

For iMonth As Integer = 0 To _
                CultureInfo. CurrentUICulture.Calendar. _ 
                GetMonthsInYear(Now.Year) - 1
    ....

/Just trying to be a good boy and use the facilities provided by the framework/

Asm?

Kā jums šķiet, vai “objektorientētais asamblers” ir oksimorons? Zinu tikai to, ka “objektorientācija” un “asemblers” vienmēr ir rādīti kā pretstati. Bet varbūt tak tomēr ir kāds gudrinieks, kurš pamanījies to apvienot?

Parse the Enum!

What if we need to save the value of an instance of an enumeration (Enum) as string and then get back the value again?

For instance, we have the following code:

Dim eDay As System.DayOfWeek = DayOfWeek.Monday

So now we can get a textual representation of eDay using the built-in ToString() method:

MessageBox.Show(eDay.ToString())

This yields a messagebox saying “Monday”. But how do we do the reverse (i.e., we know only the string representation “Monday”, but we need the enum value)? The trivial approach would be:

    Dim sStr As String = "Monday"
    Dim eDay As System.DayOfWeek
    Select Case sStr
        Case "Monday" : eDay = DayOfWeek.Monday
        Case "Tuesday" : eDay = DayOfWeek.Tuesday
            '...
    End Select

No, this sounds too dumb. We can use the built-in shared function Parse of the System.Enum class. Method accepts two parameters, the type of enumeration and the actual value being parsed.

eDay = System.Enum.Parse(GetType(System.DayOfWeek), "Monday")

This only works with option strict set to off, because Enum.Parse() returns a System.Object value. So when using option strict set to on, the code gets more obfuscated:

eDay = CType( _ 
          System.Enum.Parse(GetType(System.DayOfWeek), "Monday"),  _ 
          System.DayOfWeek)

Anyway, now we have the value! :)

String.Concat instead of &

We all know that the concatenation operator & is evil when you use it intensively.
We know writing like this is no good:

Dim s as String = ""
s &= "<"
s &= spFieldName
s &= ">"
s &= spFieldValue
s &= "</"
s &= spFieldName
s &= ">"

This is no good because a new String object is being created for every line of this code and the value is being copied to the newly created object and no optimizations can be made during compilation. One could avoid this using a StringBuilder object and calling ToString() method to achieve the same result. However the readability wouldn’t be too good.

So today I was paging through code of some library not written by me. I used Lutz Roeder’s Reflector. I came accross the following approach of string concatenation:

Dim s as String
s = String.Concat("<",  spFieldName,  ">", spFieldValue, "</", spFieldName, ">")

They had used the “Dotfuscator” to obfuscate the code of the library. As far as I know, the Reflector also makes some optimizations to the code. That’s why I’m not really sure if this is a coding approach or an effect by Dotfuscator/Reflector. Anyway, I believe it is quite a good solution: it doesn’t use much memory for execution and it’s quite readable!