Spreadsheetgear set data flags for specific column? - c#

I am attempting to do this:
IWorksheet worksheet = Factory.GetWorkbook().Worksheets[0];
IRange range = worksheet.Cells["A1"];
range.CopyFromDataTable(dataTable, SetDataFlags.None);
worksheet.Cells.Columns.AutoFit();
return worksheet;
This works great normally, however I've run into an issue. I have one column that has a really long number, possibly with zeroes in the front and I need it to be entered and displayed as text. If I do a lookup of that particular cell like:
var cell = range["U34"].Value;
The data has already been turned into scientific notation so no amount of formatting afterwards fixes it. I tried SetDataFlags.AllText and that works great, except it breaks the rest of the worksheet because all of the numbers are stored as text, which is unacceptable.
I'm at a loss of how to fix this.
Solution:
Since I'm just looking to change one column, if it's present and a lot of the columns are dynamic I went with the "preformatting" route. Find the column index from the datatable:
int ColumnIndex = -1;
for (int x = 0; x < dataTable.Columns.Count; x++)
{
if (dataTable.Columns[x].ColumnName.Equals("Whatever"))
{
ColumnIndex = x;
}
}
worksheet.Cells[0, ColumnIndex, 0, ColumnIndex].EntireColumn.NumberFormat = "#";
Then perform the CopyFromDataTable, with Flags set to None and everything is perfect!

The IRange.CopyFromDataTable(...) method can be passed in a SetDataFlags.InsertCells enum option, which allows you to pre-format your destination range so that the inserted DataTable data picks up the formatting you specify. This formatting includes a cell's IRange.NumberFormat, which can be set to "#" and specifies that input to that cell should be treated as Text.
So, if you know what columns will have these unusually-large numbers that trigger scientific notation, another option would be to pre-format your worksheet's destination range with IRange.NumberFormat = "#" and will preserve your values for these columns as-is.
Please see the documentation for the IRange.CopyFromDataTable(...) method, as it provides important information on what range needs this "pre-formatting." Also, assuming you've installed SpreadsheetGear on your machine, check out the Reporting > DataSet to Workbook example in the SpreadsheetGear Explorer Solutions for C#/VB (found in the "SpreadsheetGear" folder under the Start Menu) for a live demo of this SetDataFlags.InsertCells option.

Related

Setting colors of an entire Excel range to array of colors

I have an Excel.Range with 10 cells and I want to change its color by using a 0 based 2d array with 10 elements of Excel.XlRgbColor.
object[,] colorsTest = new object[10, 1]
{
{ Excel.XlRgbColor.rgbAliceBlue, Excel.XlRgbColor.rgbAliceBlue},
{ Excel.XlRgbColor.rgbAliceBlue, Excel.XlRgbColor.rgbAliceBlue}...
(8 more)
};
Excel.Range range = activeSheet.Range[activeSheet.Cells[1, 1], activeSheet.Cells[10, 1]];
But now when I try to set
range.Interior.Color = colorsTest;
I get a Type mistmatch error for some reason. When I try to set the range's value with the array, everything works like intended - I get the indexes of my colors pasted into the cells as values, like expected.
Any idea what could be causing this? I think the type is what it should be.
I have about 5000 rows this has to apply to so looping through them separately results in tragic performance.
Interesting idea but unfortunately it's not possible to set different color for each cell in a range they way you wanted to do that. I'm actually surprised you didn't get an error.
I also agree with "tragic performance" I guess we're talking about minutes here.
I see just a few options here
Copy format - if the colors are stable and you will always apply the same or just a few variation of them. I'd prepare the colored cells somewhere, like in range AA1:AA10 and when you want to apply the colors I'd just copy & paste format to your range
OpenXML - I believe it would be a way faster than accessing cells one by one but I assume you will code it for at least one day. I don't have too much experience with OpenXML SDK but from what I have done I can tell you it's pretty verbose

C# Excel Date value is coming as numeric value

An excel file is generated by a third party app. I am writing a utility to further process that Excel file. When I read a column containing date value, I am getting a numeric string like 05/02/2016 (dd/MM/yyyy) is coming as 42405.
I have tried using .Text, .Formula, .Value, .Value2 - all the approaches are returning the numeric value.
I know about FromOADateTime, but my requirement is to read the date value as a string, exactly the way it is displayed on the screen.
Thanks.
EDIT 1:
When I convert the column to Text in Excel, by using Format Cells and selecting Text, all the date values convert to numeric values even in Excel! Does that give any clue? Probably the third party app stores the data as numeric value, but Excel displays it as a date string on screen. I want to read the value displayed on screen.
EDIT 2:
This problem does not come with all the date values in that column. My first impression is that the third party app is not consistent while writing date values to Excel. But I have no control over it.
EDIT 3:
Here is the link to download file: http://wikisend.com/download/316956/Prob.xls . In this file, I need to read all date values in Column B as text starting from Row 13
And here is the link to the screenshot of how it looks in my machine: http://wikisend.com/download/443994/Screenshot1.jpg
EDIT 4:
Found the culprit in my code with the help of NineBerry's answer: a few lines before reading the Text property, I was calling ws.Columns.ClearFormats() and ws.Rows.ClearFormats();
I needed to do this as per this: How to get the range of occupied cells in excel sheet…, in order to correctly get the used range in the sheet!
The original problem is solved. Now the problem is how to use ws.UsedRange without calling ClearFormats() to correctly get the range of used cells.
My specific requirement is to get the range of used ROWS having data in any cells up to Col H. I Dont need the entire UsedRange in Excel, UsedRange within Col H is good enough for me.
Any solutions to this? Or should I post a new thread?
Using the Text property does give the string that would be displayed to a user.
private void button_Click(object sender, EventArgs e)
{
string path = #"C:\Test.xlsx";
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
Workbook wb = excel.Workbooks.Open(path);
Worksheet excelSheet = wb.ActiveSheet;
//Read a specific cell
Range cell = excelSheet.Cells[1, 3] as Range;
// Show text content
MessageBox.Show(cell.Text);
wb.Close();
}
If you don't see here what you see in Excel, you have to give us more details. Maybe provide a sample Excel file where a cell does not behave as expected.
This code DOES output the content of the second column in the file provided exactly as displayed in Excel:
private void button1_Click(object sender, EventArgs e)
{
string path = #"D:\Downloads\Windows\Prob.xls";
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
Workbook wb = excel.Workbooks.Open(path);
Worksheet excelSheet = wb.ActiveSheet;
//Read a specific cell
for (int i = 1; i <= 150; i++ )
{
Range cell = excelSheet.Cells[i + 1, 2] as Range;
textBox1.AppendText(cell.Text + Environment.NewLine);
}
wb.Close();
}
If you don't see that, you should check that you are actually reading the correct file, and that you do not modify the file yourself from code before reading.

Finding the number of cells in a row that has data

So I'm having a problem finding the number of rows in an excel document that has data in it. Here's what I have so far:
for (int i = 2; i <= b; i++)
{
if (!(worksheet.get_Range("A" + i, misValue).Formula == null))
{
a.Add(worksheet.get_Range("A" + i, misValue).Formula);
}
}
At the moment I'm just crudely shuffling through a large number of lines, questioning whether it's null or not, then adding the contents to a list. There has to be an easier way that google has yet to show me. Thanks for the help in advanced
I might not be understanding your question properly, but I'm guessing you're trying to find all the cells in column A that have a value in them and I'm assuming you're using Excel Interop in C#...
For that, you can use the Range.SpecialCells method.
So, for example, to get cells with constant values or formulas use:
worksheet.Range("A:A").SpecialCells(
Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeConstants |
Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeFormulas)
That will return a range you can loop through and add to your list, a....
See the documentation here
Hope this helps...

C# Interop Excel format like Excel's format as table

I'm exporting a table from SQLite to Excel (2010) in C#. It works fine. I'm using the Excel.Range.set_Value() method.
How can I format an Excel.Range like Excel's format (like a table) would?
To expand upon my comment and add to D Stanley.
Range range = ws.get_Range("A1:D5");
wrksheet.ListObjects.AddEx(XlListObjectSourceType.xlSrcRange, range, missing, Microsoft.Office.Interop.Excel.XlYesNoGuess.xlNo, missing).Name = "MyTableStyle";
wrksheet.ListObjects.get_Item("MyTableStyle").TableStyle = "TableStyleMedium1";
This example selects a rectangular range of every cell in the active sheet. Also, it uses indexed parameters of Range to get the range points. Furthermore, AddEx() (and most methods in Interop.Excel) uses default parameters so you don't have to use System.Reflection.Missing.
// define points for selecting a range
// point 1 is the top, leftmost cell
Excel.Range oRng1 = oSheet.Range["A1"];
// point two is the bottom, rightmost cell
Excel.Range oRng2 = oSheet.Range["A1"].End[Excel.XlDirection.xlToRight]
.End[Excel.XlDirection.xlDown];
// define the actual range we want to select
oRng = oSheet.Range[oRng1, oRng2];
oRng.Select(); // and select it
// add the range to a formatted table
oRng.Worksheet.ListObjects.AddEx(
SourceType: Excel.XlListObjectSourceType.xlSrcRange,
Source: oRng,
XlListObjectHasHeaders: Excel.XlYesNoGuess.xlYes);
Here's the VBA that does it:
ActiveSheet.ListObjects.Add xlSrcRange, Range("$J$10:$N$12"), , xlYes
Shouldn't be too hard to translate into an automation call. You can read the documentation as well.

Edit Range NumberFormat in existing document

I can't change column format in an existing Excel document (xlsx). Columns content are numbers actually but shown as text and therefore green triangle appear telling that cells shown as text.
So I open this document in C# app and do the following thing:
sheet_.Range[sheet_.Cells[1, 2], sheet_.Cells[rowNum, 2]].EntireColumn.NumberFormat = "0";
But it doesn't change column to appear content as numbers (they remain aligned by left side)
I know this is an old post, but I've been dealing with the same problem. I receive .xlsx files that already have green triangles denoting "Number as Text" errors. I couldn't find a way to programmatically run the Excel error-checking command "Convert to Number" that you can do by clicking in Excel, and changing the NumberFormat on cells with these errors didn't work for me, but I was able to "refresh" the cell format by using the TextToColumns method.
int lastCol = sheet.UsedRange.Columns.Count;
if(lastCol > 1)
{
for (int i = 1; i <= lastCol; i++)
{
sheet.Columns[i].TextToColumns(Type.Missing, XlTextParsingType.xlDelimited, XlTextQualifier.xlTextQualifierNone);
}
And from there you can change the NumberFormat. I happened to have long integers that were getting put into scientific notation, so I used this to make them regular integers again:
sheet.Cells.NumberFormat = "#";
(PS, if anyone finds a definitive guide on the symbols to use for customized NumberFormats, I'm still trying to find one!)
Try to access to cell value over get_Range method! for example and for what number format you want, lets say that you have in your excel cell this number : 1546,65
sheet_.get_Range("P10", "Q10").NumberFormat = "0"; // returns 1546
sheet_.get_Range("P10", "Q10").NumberFormat = "0,00"; // returns 1546,65
sheet_.get_Range("P10", "Q10").NumberFormat = "#.##0,00"; // returns 1.546,65
And you can play with these number formats!
Hope it helps you
I didn't find ideal solution to this issue and ended with the following:
sheet_.get_Range("A1", "A100").NumberFormat = "0";
for(int i = 1; i <= 100; i++)
{
sheet_.Cells[1, i].Value = sheet_.Cells[1, i].Value;
}
I know this is a old post but I stumbled over this and have a solution for this. Have you tried to not assign any NumberFormat? by default excel decides based on the cell content so you wouldnt get green triangle if you have numbers which are stored as text. If you want read values based on data type then refer this post
http://www.codeproject.com/Articles/335589/Export-Multiple-Datasets-to-Multiple-Excel-sheets
For me using the Style and the NumberFormatLocal solved the problem:
sheet_.get_Range("A1", "A100").Style.NumberFormatLocal = "0";

Categories