Friday, September 28, 2007

How to output numeric data as strings in Excel

A customer had a requirement to do this. The default implementation of export to Excel doesn't do this. I had to go looking for it. This is what I found:

'<summary>

'An overload for this function

'</summary>

Public Shared Sub DataTableToXhtmlTable(ByVal dt As DataTable, ByVal filename As String, ByVal WriteToResponse As Boolean)Dim dv As New DataView(dt)

DataTableToXhtmlTable(dv, filename, WriteToResponse)

End Sub

'<summary>

'This export method is similar to the common technique of binding a dataset to a datagrid/gridview

'and rendering the contents to produce a HTML table that Excel can understand. However the datagrid

'approach is not reliable if the data contains html characters, e.g. < or >, it produces invalid XML,

'which causes problems in Excel and OpenOffice.

'An alternative approach is to derive a GridView control that automatically sets HtmlEncode = true on

'all the BoundColumns, but this can produce very bloated output where non ASCII characters are represented

'and Excel will not decode the HtmlEncoded text.

'I found the simplest approach is to parse the dataview and write out an XHTML table. This way the

'output is guaranteed to be valid XHTML, and compatible with Excel and OpenOffice (use the HtmlDocument filter).

'</summary>

'<param name="dv"> The data source</param>

'<param name="filename"> If WriteToResponse is true, this must be a file name, otherwise a full path+file name to save the file to</param>

'<param name="WriteToResponse"> if true, Response.Writes the output to the client browser,

' otherwise writes the contents to the specified file path</param>

Public Shared Sub DataTableToXhtmlTable(ByVal dv As DataView, ByVal filename As String, ByVal WriteToResponse As Boolean)

Using sw As StringWriter = New StringWriter()sw.WriteLine(

My.Resources.ExcelBookXML.Header)

For Each dr As DataRow In dv.Table.Rowssw.WriteLine(

"<Row>")

For i As Integer = 0 To 13

Dim o As Object = dr.ItemArray(i)

If o.ToString = "" Then

sw.WriteLine("<Cell ss:StyleID='s23' />")

Else

Select Case i

Case 0

'An ordinary strgin

sw.WriteLine("<Cell ss:StyleID='s22'>" + _

"<Data ss:Type='String'>{0}" + _

"</Data></Cell>", XmlEscape(o.ToString()))

Case 1sw.WriteLine(

"<Cell ss:StyleID='s22'>" + _

"<Data ss:Type='String'>{0}" + _

"</Data></Cell>", XmlEscape(o.ToString()))

Case 2 : sw.WriteLine("<Cell ss:StyleID='s22'><Data ss:Type='String'>{0}</Data></Cell>", XmlEscape(o.ToString()))

Case 3 : sw.WriteLine("<Cell ss:StyleID='s22'><Data ss:Type='String'>{0}</Data></Cell>", XmlEscape(o.ToString()))

Case 4

'An ordinary number

sw.WriteLine("<Cell ss:StyleID='s22'>" + _

"<Data ss:Type='Number'>{0}" + _

"</Data></Cell>", XmlEscape(o.ToString()))

Case 5 : sw.WriteLine("<Cell ss:StyleID='s22'><Data ss:Type='String'>{0}</Data></Cell>", XmlEscape(o.ToString()))

Case 6

'An ordinary date

Dim StartDate As DateTime = CDate(o)

sw.WriteLine("<Cell ss:StyleID='s24'>" + _

"<Data ss:Type='DateTime'>{0}" + _

"</Data></Cell>", StartDate.ToString("yyyy-MM-dd"))

Case 7 : sw.WriteLine("<Cell ss:StyleID='s22'><Data ss:Type='String'>{0}</Data></Cell>", XmlEscape(o.ToString()))

Case 8

'A number that I want formatted as string

sw.WriteLine("<Cell ss:StyleID='s23'>" + _

"<Data ss:Type='String'>${0}" + _

"</Data></Cell>", XmlEscape(o.ToString()))

Case 9 : sw.WriteLine("<Cell ss:StyleID='s22'><Data ss:Type='Number'>{0}</Data></Cell>", XmlEscape(o.ToString()))

Case 10 : sw.WriteLine("<Cell ss:StyleID='s23'><Data ss:Type='String'>${0}</Data></Cell>", XmlEscape(o.ToString()))

Case 11 : sw.WriteLine("<Cell ss:StyleID='s22'><Data ss:Type='String'>{0}</Data></Cell>", XmlEscape(o.ToString()))

Case 12 : sw.WriteLine("<Cell ss:StyleID='s22'><Data ss:Type='String'>{0}</Data></Cell>", XmlEscape(o.ToString()))

Case Else : sw.WriteLine("<Cell ss:StyleID='s22'><Data ss:Type='String'>{0}</Data></Cell>", XmlEscape(o.ToString()))

End Select

End If

Next

sw.WriteLine("</Row>")

Next

sw.WriteLine(My.Resources.ExcelBookXML.Footer)

If (WriteToResponse) Then

Dim response As HttpResponse = HttpContext.Current.ResponseWith response

.Clear()

.Charset = System.Text.UTF8Encoding.UTF8.WebName

.ContentEncoding = System.Text.UTF8Encoding.UTF8

.AddHeader("Content-Disposition", String.Format("attachment; filename='{0}';", filename))

.ContentType = "application/vnd.ms-excel"

.Write(sw.ToString())

.End()

End With

Else

File.WriteAllText(filename, sw.ToString())

End If

End Using

End Sub

'<Summary>

' Replace < & > characters with their xml escaped equivalents

'</Summary>

Public Shared Function XmlEscape(ByVal s As String) As String

s = Regex.Replace(s, "<", "&lt;")

s = Regex.Replace(s, ">", "&gt;")s = Regex.Replace(s,

"&", "&amp;")

If s = "" Then

Return Nothing

Else

Return s

End If

End Function

Monday, September 17, 2007

Comp.Sci. vs Info.Sys

Hi,

I'm beginning to formulate an hypothesis, that I haven't designed any experiments for yet, so I can't call it a theory. It is this:

That Computer Science grads are taught C (C+, C#, whatever) and therefore have a "top-down" approach to software development. This top-down approach I define as being concerned with proper class definition, inheritence, polymorphism, etc. first, and the data layer takes care of itself, often via some Object Relational Mapper (ORM) tool.

Conversely, Information Systems grads are taught VB (and often SQL as well) and therefore have a "bottom-up" approach to software development. This bottom-up approach I define as being concerned with proper entity-relationship definition and the presentation layer is merely an extension of the database.

I do not believe either approach is superior in all circumstances: both may be better in certain instances.

It is less of a problem than the divide between Engineers and Developers. We really don't talk the same language!


I'd be interested in formulating debate around this topic, if anybody out there is also interested?

Wednesday, September 12, 2007

Passed Exam 70-547

Exam Number: 70-547

Name: PRO: Designing and Developing Web-Based Applications by Using the Microsoft® .NET Framework

Passing Score: 700

My Score: 725!!!

Result: Pass (Just)

Sectional Results (approximations):

  • Envisioning and Designing an Application (80%)
  • Designing and Developing a User Interface (85%)
  • Designing and Developing a Component (45%)
  • Designing and Developing an Application Framework (70%)
  • Testing and Stabilizing an Application (100%)
  • Deploying and Supporting an Application (80%)

This is the last exam of three (the other two being 70-528 & 70-536) which give me the new credential:

  • Microsoft Certified Professional Developer (.NET 2.0: Web)

I’m happy, but shattered. This one took a lot of study.

Thursday, September 6, 2007

Just Read The Manual

Kiaora Team,

I just discovered something interesting/important:

  • Use a separate cookie name (using the name attribute of the <forms> element) and path for each Web application. This will ensure that users who are authenticated against one application are not treated as authenticated when using a second application hosted by the same Web Server.

- Building Secure ASP.NET Applications

- Patterns and Practices

So, this means that my web.config should look like this from now on:

<authentication mode="Forms">

<forms name="StanleyAuth"

path="/"

protection="Encryption">

</forms>

</authentication>

<authorization>

<deny users="?"/>

</authorization>

Blessings,

James.