Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read data from combined Excel columns/rows using C#

Tags:

c#

excel

com

I'm trying to read data from an Excel document in C# using Microsofts COM Interop.

So far, I'm able to load the document and read some data from it. However, I need to read data from two different columns and output these as json (for a jquery ajax call)

I've made a quick prototype of how my Excel document is structured with the hope that it's a bit easier to explain ;-)

enter image description here

The method I have is called GetExcelDataByCategory(string categoryName) where the categoryName parameter would be used to find which column to get the data from.

So, i.e., if I'm making the call with "Category 2" as parameter, I need to get all the values in the C columns rows and the corresponding dates from the A column, so the output will look like this:

enter image description here

Which then needs to be transformed/parsed into JSON.

I've searched high and low on how to achieve this, but with no luck so far :-( I'm aware that I can use the get_Range() method to select a range, but it seems you need to explicitly tell the method which row and which column to get the data from. I.e.: get_Range("A1, C1")

This is my first experience with reading data from an Excel document, so I guess there's a lot to learn ;-) Is there a way to get the output on my second image?

Any help/hint is greatly appreciated! :-)

Thanks in advance.

All the best,

Bo

like image 284
bomortensen Avatar asked Mar 14 '12 14:03

bomortensen


1 Answers

This is what I would do:

using Excel = Microsoft.Office.Interop.Excel;

Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open("path to book");
Excel.Worksheet xlSheet = xlWorkbook.Sheets[1]; // get first sheet
Excel.Range xlRange = xlSheet.UsedRange; // get the entire used range

int numberOfRows = xlRange.Rows.Count;
int numberOfCols = xlRange.Columns.Count;
List<int> columnsToRead = new List<int>();
// find the columns that correspond with the string columnName which
// would be passed into your method
for(int i=1; i<=numberOfCols; i++)
{
    if(xlRange.Cells[1,i].Value2 != null) // ADDED IN EDIT
    {
        if(xlRange.Cells[1,i].Value2.ToString().Equals(categoryName))
        {
            columnsToRead.Add(i);
        }
    }
}
List<string> columnValue = new List<string>();
// loop over each column number and add results to the list
foreach(int c in columnsToRead)
{
    // start at 2 because the first row is 1 and the header row
    for(int r = 2; r <= numberOfRows; r++)
    {
        if(xlRange.Cells[r,c].Value2 != null) // ADDED IN EDIT
        {
            columnValue.Add(xlRange.Cells[r,c].Value2.ToString());
        }
    }
}

This is the code I would use to read the Excel. Right now it reads every column that has the heading (designated by whatever is in the first row) and then all the rows there. It isn't exactly what you asked (it doesn't format into JSON) but I think it is enough to get you over the hump.


EDIT: Looks like there are a few blank cells that are causing problems. A blank cell will be NULL in the Interop and thus we get errors if we try to call Value2 or Value2.ToString() since they don't exist. I added code to check to make sure that the cell isn't null before doing anything with it. It prevent the errors.

like image 71
Jetti Avatar answered Sep 20 '22 05:09

Jetti