I am using Excel as a reporting tool, for my desktop application. The app is written in C# (VS 2019).
The gist of my code is to obtain a range object from the worksheet, populate an array of null-able integers and write it back out to the same worksheet.
So far I have obtained a range of cells, where startRow is the first row highlighted in yellow:
Range startRow = (Range) input.Range["E" + row.ToString(), "K" + row.ToString()];
Initialise the local array as:
double?[,] startArray = new double?[1, 7];
Set the relevant values:
startArray[1,2] = 9.75;
And finally, write the data back:
startRow.Value2 = startArray;
When I write the array back, I get the error
The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))
In this case, I assume that it is because I have some null-able values in the array, as if I do not use a null-able array and as a result its values are zero by default, this works OK, but wites zeros out into the spreadsheet.
I did try using:
string[,] startArray = new string[1, 7];
which does work, but any fields that does have a value, are not seen as numeric and causes Excel formulae not to work.
So to my question, can I get the array to write back to Excel with nulls, or do I have to revert to using the cell object and only update the cells which contain a value?
As it happens, just the fact of writing this post has enabled me to fix it.
The simple answer is to write directly to the range only the values which contain a value.
So something like this:
for (int i = 0; i < 7; i++)
{
if (startArray[0, i] != null) startRow[1, i + 1] = startArray[0, i];
}
As for EPPlus, it looks a fantastic product, but as I already pay for an Excel license would find this a little over kill as a paid license would also be needed for EPPlus.
Related
Having some problems parsing numbers out of the following excel spread sheet.
The code:
var curQOH = toolkit.ExcelWorksheet.Cells[i, 28] as Range;
var curQAV = toolkit.ExcelWorksheet.Cells[i, 29] as Range;
if (!curQOH.Text.Contains("("))
Int32.TryParse(curQOH.Text, out lastQOH);
else
Int32.TryParse(curQOH.Value as string, out lastQOH);
if (!curQAV.Text.Contains("("))
Int32.TryParse(curQAV.Text, out lastQAV);
else
Int32.TryParse(curQAV.Value as string, out lastQAV);
The code above parses the positive numbers just fine. No issues. But it seems like it cannot parse negative number.
To my knowledge, Text is suppose to give me what the viewer sees so I would get (10) as an output. Value does give the right number but I cannot seem to parse that after casting to string. (this issue why I cant store the value as string or cast it to int, Excel cell value as string won't store as string)
Stoped using Excel Interlop and started using OpenXML Excel library
I know it is possible load a range of cell data into a system array in C#.
For Example:
Excel.Range r1 = ws.get_Range("A1", "Q55");
Array dataflds = (Array)r1.Cells.Value2;
Is there a way to do the same with the number formats for each cell in that range? Inspecting them one at a time is very slow. My attempts yield an error stating that you can not convert a string to a system array.
I am trying to use Microsoft.Office.Interop.Excel to read excel file in c#.
I want to read range of cells as it is way faster than reading cell one by one:
Range rbeg = (Range)sheet.Cells[1, i + 1];
Range rend = (Range)sheet.Cells[totalRowCount, i + 1];
Range range = sheet.get_Range(rbeg, rend);
column = (object[,])range.Value2;
The problem is when I want to get number format of cells by calling:
range.NumberFormat
I get System.DBNull. It works when I call it for single cell.
I want to distinguish between cells with numerical values and "%" values.
Any ideas?
See the documentation:
[NumberFormat] returns Null if all cells in the specified range
don't have the same number format.
What were you expecting it to do in this case?
I am converting an app from vba to C#. It's going slowly. Here's my first challenge...
In vba, I can assign an Excel range to a vba two-dimensional array:
Dim strSheetArray as Variant
strSheetArray = xlSH.UsedRange
...
debug.print strSheetArray[1,2] 'etc.
When I convert to C#, the "UsedRange" property seems to return an object. I can't seem to use that object like an array, getting code-time errors. So, how do I refer to the returned object so I can iterate through it?
And, as long as I'm at it, the cells have no type, so how do I use them (some are number, others are text, etc.) It was pretty easy in vba....
Thanks for the help.
It returns a Range Interface. You can read more about it at MSDN.
And, as long as I'm at it, the cells have no type, so how do I use them (some are number, others are text, etc.) It was pretty easy in vba....
The cells do have a type, but they are just objects.You will have to cast to what you want it to be. So if the cell is text, you will have to do something like:
(string)xlSheet.Cells[row,col].Value2
or
xlSheet.Cells[row,col].Value2.ToString();
You would have to cast to a numeric type as well if you knew they were numbers.
Edit based comments:
So if you want to get the used range you would do this:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Range range = xlSheet.UsedRange;
This will give you everything from the worksheet (I used the variable xlSheet, which is Excel.Worksheet).
Now we can iterate over this by doing:
int rows = range.Rows.Count;
int cols = range.Columns.Count;
for(int r=1; r <= rows; r++)
{
for(int c=1; c <= cols; c++)
{
Console.Write(range.Cells[r,c].Value2.ToString());
}
Console.WriteLine();
}
This will iterate over the range and basically replicate what is in your spreadsheet in the console window. I hope this helps. I also wrote a blog post on reading Excel spreadsheets using C# which you can read here if you want.
I've checked a few online resources, maybe I'm blind but I've as yet been unable to find an answer to this.
I'm uploading a file, converting it to a stream, feeding it into SpreadSheetGear. Now, I need to loop through every row and read the data (which is fine). Here is my code so far:
IWorkbook wb = Factory.GetWorkbookSet().Workbooks.OpenFromStream(file.InputStream);
IWorksheet ws = wb.ActiveWorksheet;
IRange cells = ws.Cells;
for (int i = 2; i <= cells.RowCount; i++)
{
//Code for every row
for (int x = 1; x <= cells.ColumnCount; x++)
{
//Code for every column
}
}
Here is the problem: cells.RowCount is equal to 1048576 which is clearly the Excel upper limit on number of rows. Is there a call to SpreadSheetGear that returns the number of rows that have data? I cant use a fixed amount as the spreadsheet provided could have anything from 500 to 2,000 rows.
I understand SpreadSheetGear may not be that widely used but I thought I'd chance my arm here anyway.
Cheers!
Edit :
Before somebody says use a while loop, it's possible that a row can be empty so checking for null strings is a bit of a messy one.
Answered my own question, always the way.
Anyway, eventually found IWorksheet.UsedRange which returns just the used cells.