Setting cell using excel introp changes date - c#

I'm trying to enter a date value into an excel file.
For e.g.
"05/07/19" (July 5th of 2019) and the date formate of the cell in the excel is set to "dd-MM-yy" (regional setting of the computer is also the same). But when my code enters the value into excel, value is getting changed to "07-05-19" (May 7th of 2019).
I want it to stay as "05-07-19" and also excel should consider it as a date.
I have tried different ways to set the value into an excel,
const string DATE = "05/07/19";
Application app = new Application();
Workbook workBook = app.Application.Workbooks.Open(FILE_PATH);
Worksheet sheet = workBook.Sheets[1];
Range range = sheet.get_Range("A1");
range.set_Value(XlRangeValueDataType.xlRangeValueDefault, DATE);
Range range2 = app.get_Range("A1", "A2");
range2.Cells[2, 1] = DATE;
Range range3 = app.get_Range("A3", "A3");
range3.Value = DATE;
Range range4 = app.get_Range("A4", "A4");
//Of course, It is not setting the value as a Date but text.
range4.Value = new string[] { DATE };
I want my code to behave as per the formate of the cell. If the input can be fit as a date (based on the cell formate for date), it should be considered as a date, else just a text. (The way excel behaves when the user manually input the data)
UPDATE:
So far I got to know that runtime version of excel interop (File version: 15.0.4420.1017) is v2.0 and If I run my code with target framework .Net 3.5, it is working as expected.
But the same code is having the problem if I change the target framework to .Net 4.6
Do we know, if there may any compatible interop available for .Net 4.6?

Please set the number format for the relevant cells.
As an example, do like this:
range2.NumberFormat = "DD/MM/YYYY";

Ideally excel reacts on values based on default settings and if we wish to retain our own formatting while passing values we have to prepare our destination first then put value.
I would say the code which should work as:
range2.Numberformat="dd-mm-yy";
range2.Value=DATE;

Related

how to keep the datetimeformat of excel.cell into dataset cell

Having some hard time understanding the conversion between excel file to .net object type such as DataSet or DataTable.
One issue I see in this 3rd party library (and the issue still lingers in the latest I believe) called ExcelDataReader is its conversion of datetime format.
For example the excel file where user set custom format of dd/mm/yyyy gets converted in the result of dataSet as mm/dd/yyyy after importing the excel file to the object done.
I was thinking maybe to fix this, the library code needs to passively receive the excel cell format settings, not trying to convert with its own settings.
Wonder how in the code it can be done such that
if (excelfile.row[somenumber].cell.TypeSetting == typesetting.dateTime)
{
dataset.cell[somenumber].dateTimeFormatSetting = excelfile.row[somenumber].cell.dateTimeFormatSetting
}
probably this code isn't close to be realistic, just a wild guess of what needs to be done.
ExcelDataReader loses Excel's formatting information when using AsDataSet(), which basically gives you only the raw values.
F.ex a raw date object alone does not know whether it should be displayed as 'mm-dd-yy' or 'dd/mm/yy'. For this you need the "number format string", which is ignored by AsDataSet().
To work around this, instead of calling AsDataSet(), you need to manually loop over the rows/columns using ExcelDataReader's lower level reader APIs, and using the third party library ExcelNumberFormat to format the values like Excel.
This relevant snippet from their readme shows how to format a single value from the reader object:
string GetFormattedValue(IExcelDataReader reader, int columnIndex, CultureInfo culture)
{
var value = reader.GetValue(columnIndex);
var formatString = reader.GetNumberFormatString(columnIndex);
if (formatString != null)
{
var format = new NumberFormat(formatString);
return format.Format(value, culture);
}
return Convert.ToString(value, culture);
}

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.

Spreadsheetgear set data flags for specific column?

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.

how to add conditional formatting on cells with values greater than a specific constant value using epplus

I have made an excel sheet programmatically. and now I want to add conditional formatting on a specific cell range.
The formatting type is all the cells with values greater than 0 (>0)
How to go about doing it?
In excel I can do it using an inbuilt formula of Cell Values Greater Than. But how to embed it in excel using C# and epplus?
i coudnt find an exact solution to this problem. so adding my own solution that works
var cellAddress = new ExcelAddress(
<startingRow>,
<startingcolumn>,
<endingRow>,
<endingColumn>);
var cf = ws.ConditionalFormatting.AddGreaterThan(cellAddress);
cf.Formula = "0";
cf.Style.Fill.BackgroundColor.Color = Color.LightGreen;

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.

Categories