About Excel exporting using Nikasoft NativeExcel..

I’m still looking at Excel components. From the same series so far:

This time I’ll try Nikasoft NativeExcel and follow the same procedure as in previous posts of the series.

What does it do ?

Works without Excel, creates Excel 97-2003 documents, which may contain formulas, images, formatting etc. See the feature list yourself. It seems to support everything I need.

What do I need ?

Support for data types, unicode, basic formatting, formulas, cell merge, column width – the same things as in my previous excel-component test.

What did I get ?

As already becoming a norm - functionally I got everything I wanted. Again, as I used demo version then it overwrote the top-left cell with warning “This worksheet was created by demo version of NativeExcel library”. I didn’t like that it overwrote my own text in there without warning which is more invasive than Winnovative’s extra sheet. In production I hope they’ll somehow lose it, I hope.

The file was a Excel 97-2003 xls file, And even though it provided tools to export Excel 5 and 97 version as well as CSV and a few more, it does NOT support xlsx. Not a big thing but a sign.

image 

How did I do it ?

using System;
using System.Globalization;
using System.Threading;
using NativeExcel;

public class NativeExcelTest
{
private const int DummyRows = 15;

public static void Build()
{
//prepare sheet
IWorkbook book = NativeExcel.Factory.CreateWorkbook();
IWorksheet sheet = book.Worksheets.Add();
sheet.Name = "Sample";

//create data
int currentRow = 1;
//we can use excel style range instead of coordinates.
sheet.Cells["A1:D1"].Merge();
sheet.Cells["A1"].Value = "demonstrate merge";

BuildHeaderRow(sheet, ++currentRow);
for(int i = 1; i <= DummyRows; i++)
{
BuildDataRow(sheet, i, ++currentRow);
}
BuildSummaryRow(sheet, ++currentRow);

//corrigate column widths:
sheet.Cells.Autofit();

//output result
book.SaveAs("Native_result.xls");
}

private static void BuildHeaderRow(IWorksheet sheet, int toRow)
{
sheet.Cells[toRow, 1].Value = "index";
sheet.Cells[toRow, 2].Value = "1/index";
sheet.Cells[toRow, 3].Value = "name";
sheet.Cells[toRow, 4].Value = "datetime";
sheet.Cells[toRow, 1, toRow, 4].Font.Bold = true;
}

private static void BuildDataRow(IWorksheet sheet, int dataIndex, int toRow)
{
//generate dummy data row using dataIndex for values:
sheet.Cells[toRow, 1].Value = dataIndex;
sheet.Cells[toRow, 2].Value = 1.0M / dataIndex;
sheet.Cells[toRow, 3].Value = "Ilus õõvaöö nr "
+ dataIndex.ToString(CultureInfo.InvariantCulture);
sheet.Cells[toRow, 4].Value = DateTime.Today.AddDays(dataIndex);
}

private static void BuildSummaryRow(IWorksheet sheet, int toRow)
{
sheet.Cells[toRow, 1].Formula = String.Format("=AVERAGE(A{0}:A{1})", toRow - DummyRows, toRow - 1);
sheet.Cells[toRow, 2].Formula = String.Format("=SUM(B{0}:B{1})", toRow - DummyRows, toRow - 1);
sheet.Cells[toRow, 4].Formula = String.Format("=D{0}+1", toRow - 1);
//it didn't get the formula type correctly.
sheet.Cells[toRow, 4].NumberFormat
= Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern;
}
}


Some subjective numbers:

  • ~64 lines of code (including empty lines, usings, etc)
  • runs approx 200-240 ms on E8300 @2.83GHz, 4GB RAM.

What do I think ?

Having previously tried Winnovative component, the transition was smooth and without serious problems. All differences for my simple testcase were rather small and syntactic. Maybe I’m biased, but it felt a bit messier than Winnovative component. But as there is also price difference then better try it out yourself before choosing one or the other.

The good

  • mostly managed code, .Net fw 2.0
    • Requires windows as there’s reference to GDI32.dll
  • relatively cheap
    • $140 (registered user licence)
      • it seems there it may be with source code but without the right to modify
      • not sure if licencees are named developers or how the number of development machines matter.
      • unlimited deploy
    • $450 (site licence)
      • source code + right to recompile
      • All employees can develop
      • unlimited deploy
  • Probably single dll deployment (~0.5 MB)
  • Seems to do everything I need
  • decent API
    • friendly and flexible cell referencing tools, similar to those of Winnovative.
      • indexed (row 1, col 1) or “A1”-style
    • no adding of empty cells/rows as for CarlosAG.
  • Some documentation in web (mostly in the form of code samples

The bad:

  • Not free
    • see the prices mentioned above. Not much but more than nothing.
  • No xlsx
    • It probably is not so important to end-users, but I like the idea of the new format. Not to mentioned this is the format to be supported by Excel longer and better than the older one.
  • No xmldoc included with demo dll
    • The documentation is in web though, maybe will be included after buying the licence.
  • slower than any component I’ve seen
    • 200ms-250ms for the trivial testcase. This is 4-6 times slower than other components I’ve tested. Uh-oh, this is no small difference.
  • Some weird things in API
    • prefixes, like “xl”, “mso”, “H”, “V”. This smells of bad style.
    • interfaces & factories for everything. Seems unneccessary complex design for simple things. Debugging and code readability suffers because of actual class hiding.
  • Lots of releases. 
    • started in 2006, but since the start of 2009 there has been 19 releases, including sometimes with just 1 day apart. They are either really fast at responding to bug notices or there are quality problems. Not sure which.
  • Uncertainty for demo vs licenced version
    • No information if/how the demo version and registered assemblies differ or how licence existance is verified at runtime, does the assembly remain the same, etc.

About avoiding Excel Exporting with Aspose Cells for .NET ..

I’m still looking at Excel components. From the same series so far:

I also wanted to try Aspose Cells for .NET but gave up before even downloading the code, because:

  • Their website was annoyingly heavyweight
    • which reminded me of hard times working with Infragistics components with feature overflow obstructing productivity. Aspose website smelled the same.
  • The dll only download was 13 MB.
    • That’s quite a lot.
    • There’s also 42 MB version, I better not use my imagination what it will install on my machine.
  • The prices START from $900 and go up to $10k+.
    • this without doubt the most expensive component compared to those I’ve seen so far. Too expensive.
  • They required me to register to download the trial version.
    • Why would they need registration for trial version ?
    • Registration form included mandatory fields for my address and telepone..
    • Sorry, I want to try your software not to give you my personal data for something I probably will not end up using. Aspose, this is a really unfriendly way to get new customers!

So I didn’t try their component. Don’t get me wrong. The compnent may be good and powerful and shine with quality and support worthy of Corporate tag, but I’m looking a simple & small & cheap.. I already have better alternatives without registration or before even looking at their API or features.

About Excel exporting using Winnovative Excel Library for .NET

In search for a good managed Excel exporting tool I’ve come to test a Excel library from Winnovative. I’ll follow the same procedure as in my previous Excel-related post about CarlosAG component for easier comparison..

What does it do ?

Create xls/xlsx documents, including containing formulas, images, comments, charts, etc. Operate with CSVs, load data from DataTables, etc. See the feature list yourself.

What do I need ?

Support for data types, unicode, basic formatting, formulas, cell merge, column width – the same things as in my previous excel-component test.

What did I get ?

Functionally - everything I wanted. Actually for not having licence I got one extra sheet reminding me that fact, but that is not going to be the issue for production environments.

The file was decent xlsx-file, I also briefly tested getting the older xls_2003-file and it seemed to be working as well. No warning on open.. just such file:

image

How did I do it ?

using System;
using System.Globalization;
using System.Threading;
using Winnovative.ExcelLib;

public class WinnovativeExcelTest
{
private const int DummyRows = 15;

public static void Build()
{
//prepare sheet
ExcelWorkbook book = new ExcelWorkbook(ExcelWorkbookFormat.Xlsx_2007);
ExcelWorksheet sheet = book.Worksheets[0];
sheet.Name = "Sample";

//create data
int currentRow = 1;
sheet["A1:D1"].Merge(); //wow, we can use excel style range instead of coordinates.
sheet["A1"].Text = "demonstrate merge";

BuildHeaderRow(sheet, ++currentRow);
for(int i = 1; i <= DummyRows; i++)
{
BuildDataRow(sheet, i, ++currentRow);
}
BuildSummaryRow(sheet, ++currentRow);

//I don't like the default it offered so I'm setting it myself:
sheet[currentRow - DummyRows, 4, currentRow +1, 4].Style.Number.NumberFormatString
= Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern;

//corrigate column widths:
sheet.AutofitColumns();

//output result
book.Save("Winnovative_result.xlsx");
}

private static void BuildHeaderRow(ExcelWorksheet sheet, int toRow)
{
sheet[toRow, 1].Text = "index";
sheet[toRow, 2].Text = "1/index";
sheet[toRow, 3].Text = "name";
sheet[toRow, 4].Text = "datetime";
sheet[toRow, 1, toRow, 4].Style.Font.Bold = true;
}

private static void BuildDataRow(ExcelWorksheet sheet, int dataIndex, int toRow)
{
//generate dummy data row using dataIndex for values:
sheet[toRow, 1].Value = dataIndex;
sheet[toRow, 2].Value = (1.0/dataIndex); //decimal is not recognized as number, by doc floats are.
sheet[toRow, 3].Value = "Ilus õõvaöö nr " + dataIndex.ToString(CultureInfo.InvariantCulture);
sheet[toRow, 4].Value = DateTime.Today.AddDays(dataIndex);
}

private static void BuildSummaryRow(ExcelWorksheet sheet, int toRow)
{
sheet[toRow, 1].Formula = String.Format("=AVERAGE(A{0}:A{1})", toRow-DummyRows, toRow-1);
sheet[toRow, 2].Formula = String.Format("=SUM(B{0}:B{1})", toRow-DummyRows, toRow-1);
sheet[toRow, 4].Formula = String.Format("=D{0}+1", toRow-1);
}
}


Some subjective numbers:

  • ~64 lines of code (including empty lines, usings, etc)
  • runs approx 55-60 ms on E8300 @2.83GHz, 4GB RAM.

What do I think ?

I may be a bit biased toward them because I’ve used their PDF libraries before, but it DID feel good to code this API, clean and simple.

The good

  • Fully managed code, .Net fw 2.0
  • Single dll deployment (~3.5 MB)
  • Seems to do everything I need + more
    • by documentation, did not try them all.
    • images, comments, hidden columns, DataTable to sheet, etc ..
  • Good sleek API
    • you don’t get drowned in methods but you can do a lot with the ones given.
    • very friendly and flexible cell referencing tools
      • indexed (row 1, col 1) or “A1”-style
      • the same for cell ranges
    • dynamically tracking the cells to use:  no manual creation of 100 empty lines to add a single value to 100th row.
    • applying styles on the fly to cells/ranges. no manual messing with prepared styles unless you want to.
  • Automatic cell value type detection
    • no need to format datetimes (unless you want to) or think about decimal separator.
  • Good documentation
    • sample project in package.
    • xmldoc alongside dll
    • helpful user guide (I had two questions during this testing, I found both answers with less than a minute from the manual.
  • Respectable company
    • For all the bugs I’ve seen in their products, I’ve seen also the release to fix it.
    • there is tech support.
  • Fully functional evaluation possible
    • Can test everything before buying. The only addition is one extra sheet in file reminding that you cannot go live without a licence.
    • The same dll as the licenced version. Adding a licence 2 days before release will not give dll-problems.

The bad

  • It’s not free
    • prices start from 350$. Too expensive to buy for personal use, but for enterprises this is good value for the money.
    • licence key should be stored within system.
  • It’s not open source
    • no legal way to know or modify what the component does..
  • .NEt requirements
    • it requires System.Web which means it cannot be used with .NET FW 4 client profile. This may be important in some scnearios.
    • it requires .NET 2.0, but i don’t think this is a problem. FW 1.1 applications should have died out a long time ago.
  • Noticable dll size
    • 3.5MB is not too heavy and we have tons of RAM and HDD but smaller size would be even nicer.
  • Could be slower than some alternatives
    • I didn’t do proper performance-testing but for this ultrasmall sample file it was ca 25% slower than CarlosAG.
  • Decimals are not automatically recognized as number types.
    • floats can be used instead or kept as general type (default). Not sure if this is a excel limitation or Winnovative component optimization.

About Excel exporting in CarlosAG way..

I was looking for managed code component for excel exporting and happened to test a freeware component named CarlosAG Excel XML Writer Library. The following contains my thoughts about the pros and cons..

What does it do?

“This library allows you to generate Excel Workbooks using XML, it is built 100% in C# and does not requires Excel installed at all to generate the files. It exposes a simple object model to generate the XML Workbooks.
It supports several features for generating Excel Workbooks including:

  • Formatting
  • Alignment
  • Formulas
  • Pivot Tables
  • and more... “ (From carlosag.net)

This is nice, I suppose, but these keywords are not good enough for me. I want to try it out and see what the developer sees and what exactly will end up in the file.

what do I need ?

The excel functionality I want is quite simple actually:

  • to support data types
  • to support unicode

I’ll also try out fancier things which I foresee myself using at some point:

  • basic formatting (background colors, bold, borders would be nice)
  • formulas – it can avoid tracking values across rows/cols in code
  • cell merge
  • setting column width

For testing I’ll create a excel file programmatically, trying to use these features..

What did I get ?

I could get my needs fulfilled with some minor struggling. The output file is xml, schema seems similar to the one described in:
http://en.wikipedia.org/wiki/Microsoft_Office_2003_XML_formats
.

This is the output in excel with no modifications:

image

How did I do it?

This is the code I used. The chosen methods may not be optimal but it does indicate the API you could end up using..

using System;
using System.Globalization;
using CarlosAg.ExcelXmlWriter;


public class CarlosAGTest
{
private const int DummyRows = 15;
private const string HeaderStyleName = "headerStyle";
private const string DateStyleName = "dateStyle";

public static void Build()
{
//prepare sheet
Workbook book = new Workbook();
Worksheet sheet = book.Worksheets.Add("Sample");

//delcare header style
WorksheetStyle style = book.Styles.Add(HeaderStyleName);
style.Font.Bold = true;

WorksheetStyle dateStyle = book.Styles.Add(DateStyleName);
dateStyle.NumberFormat = "Short Date";

//create data
sheet.Table.Rows.Add(BuildMergedRow());
sheet.Table.Rows.Add(BuildHeaderRow());
for(int i = 1; i <= DummyRows; i++)
{
sheet.Table.Rows.Add(BuildDataRow(i));
}
sheet.Table.Rows.Add(BuildSummaryRow());

//set column width:
sheet.Table.Columns.Add().Width = 5;
sheet.Table.Columns.Add();
sheet.Table.Columns.Add().Width = 150;

//output result
book.Save("CarlosAG_result.xls");
}

private static WorksheetRow BuildMergedRow()
{
WorksheetRow row = new WorksheetRow();
var lastCell = row.Cells.Add("demonstrate merge");
lastCell.MergeAcross = 3;
return row;
}

private static WorksheetRow BuildHeaderRow()
{
WorksheetRow row = new WorksheetRow();
//demonstrate overloads of adding cell contents.
row.Cells.Add(new WorksheetCell("index") { StyleID = HeaderStyleName });
row.Cells.Add("(1/index)", DataType.String, HeaderStyleName);
row.Cells.Add(new WorksheetCell("name", DataType.String, HeaderStyleName));
row.Cells.Add("dateTime", DataType.String, HeaderStyleName);
return row;
}

private static WorksheetRow BuildDataRow(int rowIndex)
{
//generate dummy data row using rowIndex for values:
WorksheetRow row = new WorksheetRow();
row.Cells.Add(rowIndex.ToString(CultureInfo.InvariantCulture), DataType.Number, null);
row.Cells.Add((1.0M/rowIndex).ToString(CultureInfo.InvariantCulture), DataType.Number, null);
row.Cells.Add("Ilus õõvaöö nr " + rowIndex.ToString(CultureInfo.InvariantCulture), DataType.String, null);
row.Cells.Add(DateTime.Today.AddDays(rowIndex).ToString("s"), DataType.DateTime, DateStyleName);
return row;
}

private static WorksheetRow BuildSummaryRow()
{
WorksheetRow row = new WorksheetRow();
var averageCell = row.Cells.Add();
averageCell.Formula = "=AVERAGE(R[-" + DummyRows + "]C:R[-1]C)";

var sumcell = row.Cells.Add();
sumcell.Formula = "=SUM(R[-" + DummyRows + "]C:R[-1]C)";

row.Cells.Add();

var plusOneCell = row.Cells.Add(null, DataType.DateTime, DateStyleName);
plusOneCell.Formula = "= R[-1]C + 1";
return row;
}
}


A few subjective numbers:

  • The file was generated with approx 40-50 ms on E8300 @2.83GHz, 4GB RAM.
  • 88 lines of code (including empty lines, using-statements, etc).

What do I think ?

If you are low budget then CarlosAG is certainly a good tool to use. Far from ideal, though.

The good:

  • It did everything I wanted
  • Free. no cost, use as you want.
  • Fully managed code, requires just .net FW 1.1
  • Simple deplopyment  - just a single ~100k dll.
  • Reasonably simple API.

The bad:

  • no source code
    • just the one from reflector
  • no documentation
    • no xmldoc file for dll, chm in website was broken and failed to show a single page of it.
  • no automatic value formatting
    • cell values have to be set as strings, the of API user has to manually format contents to be saved into XML. What format is expected is not obvious.For example: Datetimes, decimal separators, etc. This could lead to hard to debug problems.. and it did.
  • Probable lack of support
    • Developer seems to have made this library for fun, this could mean loss of quality and support. For example, last realease was in 2005. It is foreseeable that problems have to be solved by yourself, digging knee-deep into reflector-generated code. For code written in .net FW 1.1, this could be ugly.
  • API lacks some comfort-features

    • You have to create lots of rows and cells and columns. To add something to n-th row you have to ensure all rows up andincluding n-th row are created. same for cells, and columns.

  • No native xls/xlsx output.

    • just xml with <?mso-application progid='Excel.Sheet'?>

  • The formula input language in unknown to me
    • I'd prefer to write exactly what I would write in excel. No doubt the given langugage could be more helpful but it adds to the learning curve. For example I’m using "=SUM(R[-30] C:R[-1]C)" instead of “=SUM(A1:A30)”.

Links

Official site:
http://www.carlosag.net/Tools/ExcelXmlWriter/

Sample for exporting dataset contents:
http://www.sitepoint.com/blogs/2006/08/22/making-excel-the-carlosag-way/

Sellest kust testimiseks IE5.5-8 leida..

Veebidisaini tehes on tavaline see, et kõik ilusad plaanid ebaõnnestuvad, sest mingis dokumendis on nõue, et “peab toetama Internet Explorer 7+” vms. Ja siis sa istud oma IE8 peal ja mõtiskled, kellel/millises masinas võiks vastavat brauserit leida. Ohh, tüütu!

Pisut abi on ehk utiliidist IETester, mis võimaldab mingi täpsusega emuleerida vanemaid IE versioone:
 image
Kui olla pisut paranoiline, siis lõpptestiks ma seda brauserit ei usalda, kuid arenduse-aegseks kiirtestiks küll.

Windows 7 kasutajatel on üsna lihtne viis ka IE6 saamiseks. Nimelt on Windows XP Mode koosseisus tolle aja brauser. Kui sul on XP Mode juba olemas, on sul ka päris IE6 juba olemas.