Word to Markdown converter

February 2nd, 2006

Some smart people who didn’t want to teach users how to code in HTML invented Textile markup language

Someone more lazy invented MarkDown syntax which is much easier to learn. MarkDown is really nice for small content management systems, blogging engines etc.

For instance, to mark text as bold, you write the “bold text” like “__bold text__”. Other rules can be found in the syntax page.

However, when you have a MS Word document with several pages of bolds, italics and lists, you don’t really want to re-code all the markup.

This is why I wrote a simple macro for converting the most trivial things automatically. This macro does:

  • Replace bold and italics
  • Replace headings (marked heading1-6)
  • Replace numbered and bulleted lists

It’s very buggy, I believe it hangs on larger documents, however I’m NOT stating it’s a stable release anyway! :-) Experimental use only, recode and reuse it as you like, post a comment if you’ve found a better solution.

Click here to download the code.

To use the code:

  • open WinWord,
  • press Alt+F11 to open the VBA editor,
  • right click the first project in the project browser
  • choose insert->module
  • paste the code from the file
  • close macro editor
  • go tools>macro>macros; run the macro named MarkDown

cmdSave.Enabled = False

January 11th, 2006

Nemaz nav prātīgi domāt, ka, ASP.Net kontrole (piemēram, poga), kas it kā ir “atspējota” (disabled, not enabled), patiesībā tāda ir. Vienīgais, ko patiesībā ASP.Net izdara, ir, ģenerējot HTML kodu, kontroles kodā ieraksta disabled=true.

Taču, ja šo pogu klienta pusē atkal “iespējojam” (eneiblojam), piemēram, ar šāda te:

javascript:( 
    function(){
      d=document;
      l=d.getElementsByTagName("INPUT");
      for(var i=0;i<l.length;i++){
         l[i].disabled=false}
 }())

JavaScript bookmarkleta palīdzību, ASP.Net neveiks nekādas servera puses pārbaudes, vai poga ir bijusi ieslēgta, vai nav. Tas jādara pašiem. Vislabāk nemaz nedot lietotājam rokās pogu, kuru nevar nospiest, bet, ja gribas saglabāt skaistu interfeisu, tad cmdSave_Click(...) kods jāpapildina ar pārbaudi, vai poga šobrīd vispār ir ieslēgta.

Paldies par uzmanību :-)

Finding SPListItem by its ID

December 19th, 2005

I just found out that some operations in my SharePoint application run quite slow when used on lists containing large amounts of listitems. In the particular case it was approximately 2,500 items in the list.

The result is: NEVER use this code construction to find an element by its ID:

oList = oWeb.Lists("LongList")         'gets the list object
oItem = oList.Items.GetItemById(123)   'finds the element within the list in the list

You should rather use this one:

oList = oWeb.Lists("LongList")         'gets the list object
oItem = oList.GetItemById(123)         'finds the element within the list in the list

The big mistake is that accessing the “Items” property of the SPList object oList creates an SPQuery object in background to read all the items in particular list and then GetItemById() method of the SPListItemCollection (oList.Items is a SPListItemCollection object) runs a loop, looking for an item with ID attribute set to the value 123.

However, if you use the second code example the SPList ojbect oList creates an SPQuery object in background to read only one object having ID attribute set to 123, i.e.:

<Where><Eq><FieldRef Name="ID"></FieldRef><Value Type="Integer">123<Value></Eq></Where>

and then returns the element it found.

The same applies to the DeleteItemById() method. I had to work around in a bit different manner:

'oList.Items.DeleteItemById(123) 'this was the original code
oList.GetitemById(123).ListItems.DeleteItemById(123) 'this is the improved code

As you can see, the improved code first finds the list item by its ID, then accesses the ListItems property (which is again SPListItemCollection) and executes a DeleteItemById() command on the particular collection where the size of the collection is 1.

A really difficult workaround was needed to fix the AddNewItem function where I had code like this:

Dim oNewItem as SPListItem
oNewItem = oList.Items.Add()

Again, accessing the Items attribute leads to reading all the items in the list. To avoid that, I created a SPQuery object that never returned any elements, then called Add() method on the collection returned by the query.

'reads all items having id=0. Should return no rows
oEmptyQuery.Query = "<Where><Eq><FieldRef Name='ID' />" & _
        "<Value Type='Counter'>0</Value&gt;</Eq></Where>"
oItemColl = oList.GetItems(oEmptyQuery)
oNewSPItem = oItemColl.Add()    'adds an item to the empty list
'saves the new item and re-reads it from SharePoint
oNewSPItem.Update()
oNewSPItem = oList.GetItemById(oNewSPItem.ID)

The two last lines were needed because it seems that the field collection is not geting populated when a query returns no rows. However, my code didn’t seem to run nice without the last two rows.

Web izstrādātātāju bookmarklets

November 11th, 2005

Izstrādātājot lietas tīmeklim, reizēm gribas pārliecību, ka lapa tiek tiešām pieprasīta par jaunu no servera, nevis izmantota IExplorer (vai citam pārlūkam pēc izvēles) pieejama kešota versija.

Parasti ar šo vēlmi tieku galā, pierakstot URLim galā kaut ko līdzīgu “&bubu”.
Nupat uzrakstīju bookmarkletu, kurš dara ko līdzīgu - ja URLī nav parametra TmpPart, tad to pieliek, ja tāds jau ir, tad tam piekabina galā kādus papildus burtus.

Bookmarkleta teksts (salauzts pa rindām, savelciet kopā, lai darbotos):

javascript:(function(){
    var sL = document.location+'';
    var s="";
        if (sL.indexOf('?')==-1) 
            s = sL + "?TmpPart=x"; 
        else 
            if (sL.indexOf('TmpPart=')==-1) 
                s=sL+"&TmpPart=x"; 
            else 
                s = sL.replace(/(TmpPart=)(x+)/g,"$1$2x");
    document.location=s;
    }())

SPUser? SPException!

October 13th, 2005

Something on SharePoint(TM) again. Either you love it or hate it, you have to work around all the pitfalls anyway.

So we all know that in SharePoint you can allow people and assign them SharePoint roles in two ways:

  • creating a “Sharepoint User” within the portal and assigning roles to the user,
  • adding a domain group to users and assigning roles to a particular group.

The first case is the easy one. The second is not. Read the rest of this entry »

Does this user belong to that domain group?

October 13th, 2005

UPD: This works only on LDAP groups and LDAP:// provider, not WinNT groups!

If we know two things - a login name of a user for instance northwind\JohnDoe and a domain group northwind\board. We want to check if John Doe belongs to the “board” group or not.

This is how you find it: IsUserMember( "northwind\JohnDoe", "northwind\board")

Read the rest of this entry »

Calculated fields in CAML

September 26th, 2005

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 0×81020024. 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

September 26th, 2005

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?

September 23rd, 2005

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?

Spell the word

September 22nd, 2005

A tiny solution for the common English spell-by-letter problem. Written by me, plain PHP. Sources available on demand.

My favourite word, mississippi.