Thursday, November 26, 2009

Converting a word document to use unicode characters

One of my friend recently had a problem like this. He wanted some word documents to be converted to Unicode. These files are in Sinhala but not in Sinhala unicode. They are in plain English letters but based on the font-type only they were displayed in Sinhala. What he wanted is to convert these documents to use Sinhala unicode characters. Since he is from Java background he wanted me to bring in some help as how to do it using .NET.

Our approach was something like this. Read thru the document, get all the words and check their font type , and if that font type is a font that uses English letters to be displayed in Sinhala(e.g. Kaputa, Thibas) we would replace the characters with a matching unicode character. Hope this approach is fair enough? If you guys could think of something smarter, please do let me know.

Here is what i do,

Declare some private members,


#region Private Members

Document wordDoc;
ApplicationClass wordApplication = new ApplicationClass();

#endregion


In a button event, open a dialog box and get the document to be converted;


DialogResult dialogResult = openFileDialog1.ShowDialog();
object documentPath;
object o_null = System.Reflection.Missing.Value;

if (dialogResult == DialogResult.OK)
{
maskedTextBox1.Text = openFileDialog1.FileName;
documentPath = openFileDialog1.FileName;

wordDoc = wordApplication.Documents.Open(ref documentPath, ref o_null, ref o_null, ref o_null, ref o_null, ref o_null,
ref o_null, ref o_null, ref o_null, ref o_null, ref o_null,
ref o_null, ref o_null, ref o_null, ref o_null, ref o_null);

}


In another button event , do the convertion ;



Words words = wordDoc.Words;
IEnumerator enumerator = words.GetEnumerator();
object o_null = System.Reflection.Missing.Value;


while (enumerator.MoveNext())
{
Range range = enumerator.Current as Range;
Microsoft.Office.Interop.Word.Font font = range.Font;

string word = range.Text.Trim();
char[] characters = word.ToCharArray();
char[] newCharArray = new char[characters.Length];

for(int i=0 ; i < characters.Length ; i++)
{
//Should take the proper character from the mapping
newCharArray[i] = 'S';
}
string newWord = new string(newCharArray);

if (!string.IsNullOrEmpty(word))
{
range.Text = range.Text.Replace(word, newWord);
enumerator.MoveNext();
}
}



Finally save the document as a new one in another event handler,


Object oSaveAsFile = (Object)"C:\\SampleDoc.doc";
object o_null = System.Reflection.Missing.Value;

wordDoc.SaveAs(ref oSaveAsFile, ref o_null, ref o_null, ref o_null, ref o_null, ref o_null,
ref o_null, ref o_null, ref o_null, ref o_null, ref o_null,
ref o_null, ref o_null, ref o_null, ref o_null, ref o_null);

Friday, November 20, 2009

Cannot place .js files in Themes folder in ASP.NET MVC

Yes! I have been struggling with this for couple of days and it is a problem. The MVC engine only parses .css files from the Themes folder. So if you are used to put .js files in your Themes folder (a habit of ASP.NET designers), well you have to think twice here. Whether you absultely need .js files in the Themes folder ? Otherwise dont put them and expect the framework to automatically dump them to the response. You have to explicitly put a script references in the Master page.

Cheers!
/Bumble Bee.

Thursday, November 19, 2009

WebMethods in aspx and calling them thru javascript

I came across a situation today which I thought worth making a note about !

Problem : I have a collapsible grid. Where upon clicking a certain button, there should appear another row with some additional fields. When the grid is created the table which contains my dynamic row is getting dumped to the output stream as follows,

System.IO.StringWriter sw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htw = new System.Web.UI.HtmlTextWriter(sw);
table.RenderControl(htw);
the table object basically contains few text box controls (ASP.NET) and labels. The problem is when i define a event handler for text change event in the text box controls, they do not wireup properly. And hence I cannot make them to do a asynchronous postback to do save their values upon leaving the text boxes. This is purely due to fact that the html content for these controls are created then and there and they wont capture these during the page-life cycle.

Solution : One solution is I can call a javascript function from either onleave or onblue events and then do a postback on that. Than doing a post back and let the full page lifecycle to run, if i can call a method in the page and do the expected saving, it would be worth it. This is the first time I used this technique but there may be guys who are experts on this. Just correct me if there are is any false in what i say :)

Step 1 : Define a web method is the webpage (yes in the web page, i did not know about if that is possible to have a web-method in any other place than a asmx but it can be done. Just have a public static method and attribute it with [WebMethod]). In my situation it was not a page that i had to deal with but it was a User Control. And here is the other problem. [WebMethod] s are not allowed in user controls. They can only be placed in .aspx pages. So how I am going to resolve the issue. I put my [WebMethod] in the page that contains my user control . Then define a static method in the user control and call it thru the [WebMethod]. Another issue! my user control is a instance member and i cannot call a instance member thru a static method. Hack: make the user control a static member thru the designer.cs [Are there any side affects of doing this, I dont think so ;)]

[WebMethod]
public static void DynamicTextBoxTextChanged(string invoiceUniqueId, string textBoxValue, string textBoxType)
{
<>.DynamicTextBoxTextChanged(invoiceUniqueId, textBoxValue, textBoxType);
}


In the user control,

public static void DynamicTextBoxTextChanged(string invoiceUniqueId , string textBoxValue , string textBoxType)
{
//Logic to do the saving
}


Step2 : Now we are half way done. Only thing left is to call the WebMethod thru a javascript in the page.

As simple as this,

function CallPageMethod(key, textBox, textBoxType) {

PageMethods.DynamicTextBoxTextChanged(key, textBox.value, textBoxType);
}
and my text box will have to have a attribute like this onchange="javascript:CallPageMethod('somekey' , this , 'sometype')"

We are not quite done yet, where does this PageMethods comes from? and how does it know that there is a [WebMethod] called DynamicTextBoxTextChanged in my page? That happens thru the ScriptManger. The ScriptManger should have the attribute EnablePageMethods="true".

And that is it. It should good to go!

Hands off the keyboard,
Bumble Bee