by Mathias 9/4/2008 6:19:00 PM

 [Edit, Sept 5, 2008: nothing incorrect in the following post; however, if I had Google'd first, I would have found that DateTime date = DateTime.FromOADate(d), where d is a double, does exactly the job...]

The project I am currently working on requires reading some data from an Excel workbook into a .NET calculation engine written in C#. Most of my reads follow this pattern: read a named range into an array of objects, then convert the object to the appropriate .NET type.

public static object[,] GetRangeAsArray(Excel.Worksheet sheet, string rangeName)
{
    Excel.Range range = sheet.get_Range(rangeName, Missing.Value);
    object[,] rangeAsArray = range.Value2 as object[,];
    return rangeAsArray;
}

However, I ran into an issue reading dates. Excel stores dates as doubles, which encode the number of days elapsed since January 0, 1900 (Yes, January 0). As a result, the object stored in the array is a double, and the Convert.ToDateTime(double) method throws an InvalidCastExpression, so standard conversion doesn’t work.
If you look a bit deeper into it (here is a very comprehensive page on the topic), you will discover some interesting idiosyncrasies of the date encoding in Excel. For instance, back in the days, the Excel team knowingly implemented a bug to replicate a known bug of Lotus, for the sake of backwards compatibility.
Here is the quick method I wrote to perform that conversion, addressing these issues:

public static DateTime ConvertToDateTime(double excelDate)
{
    if (excelDate < 1)
    {
        throw new ArgumentException("Excel dates cannot be smaller than 0.");
    }
    DateTime dateOfReference = new DateTime(1900, 1, 1);
    if (excelDate > 60d)
    {
        excelDate = excelDate - 2;
    }
    else
    {
        excelDate = excelDate - 1;
    }
    return dateOfReference.AddDays(excelDate);
}

More...

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
by Mathias 8/28/2008 6:22:00 PM

I just completed my first real-life VSTO project, and I am officially a convert: I can do everything I did in VBA, using mature languages like C#, and the comfort of the Visual Studio development tools.

Everything has not been smooth, though. I struggled quite a bit initially with deployment, a problem which just does not exist with VBA. However, after some digging, I came across this great post, which provides comprehensive step-by-step guidelines on setting up an add-in project for Office 2003.

At that point, I thought my issues were over, and I just cruised along, happily coding in C#. And then I decided that I would extract the logic of my calculation engine in a separate dll, which I would reference in my Excel add-in as a “satellite assembly” – and had a bad surprise. On my development machine, everything worked beautifully, and when I ran the installer on a clean machine, it installed my add-in without any complaint (The satellite dll was even added to the add-in folder), but somehow, the add-in did not run. No error message, no indication of a problem, but where I expected my dll to perform calculations, nothing happened.

More...

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
by Mathias 7/13/2008 6:42:00 PM

I was just reading this post on Juan Carlos Méndez-García's blog, where he describes when and how to use harmonic averages. I hadn't seen that average in a long while, and thought his example provided a good illustration as to why this seemingly odd way to compute averages would make sense.
Practically, there is one issue, though: Excel doesn't come up with a built-in Harmonic Average function. I thought I would give a shot at writing a user-defined function that does just that. The function I wrote mimics SUMPRODUCT(), but is called HarmonicAverage, and takes 2 ranges as arguments. The first range is the weight of each observation, the second the value of the observation.

More...

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
by Mathias 7/2/2008 11:19:00 AM

If you have been looking at my recent bookmarks, you may have noticed a pattern: they all revolve around Excel and VSTO. The reason is that I am starting multiple Excel development projects in the next few weeks. I am very experienced in VBA and Office development, but after 4 years of writing C# code in Visual Studio, I have been spoiled, and VBA suddenly feels very painful to work with, as if I were traveling back in time to the middle-ages of development.

Fortunately, there is now an alternative: with VSTO, you can add custom features to classic Office applications, using .NET languages and the comfort of Visual Studio 2008. So I thought it was time to give VSTO a shot.

My first project was to establish a simple way to expose the add-in functionality to the user through menus. I started from this article, and adapted the code to encapsulate the menu-related behavior in one easy-to-use class, the MenuManager.

The sample add-in works with Office 2003 and 2007, and Windows XP and Vista. It installs an add-in which creates its own menu in Excel, “My Add-In”, containing two choices, “Do This” and “Do That”. When these are clicked, message boxes pop up, displaying if the user has selected to "Do This" or "Do That", and the name of the currently active sheet.

More...

Currently rated 4.5 by 2 people

  • Currently 4.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
by Mathias 6/8/2008 6:47:00 AM

One of my clients recently asked me to modify an Excel model, so that the adoption of products entering the market would follow a S-curve. After some digging and googling, I came across this excellent post by Juan C. Mendez, where he proposes a clean and very practical way to use the logistic function, and calibrate it through 3 input parameters: the peak value, and the time at which the curve reaches 10% and 90% of its peak value.

The beauty of his approach is that his function is compact so it can be typed in easily in a worksheet cell, and the input very understandable. However, I found it a bit restrictive: transforming it for values other than 10% and 90% requires some recalibration, and more importantly, it cannot accomodate values that are not "symmetrical" around 50%.

So I set to work through a generalized solution to the following problem: find a S-Curve that fits any arbitrary value, rather than just 10% and 90%.

More...

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5