I currently have an excel sheet with one of the columns being in the date format.
What I see when I open up the spreadsheet is something like 12/29/09 and the program sees 40176.
I figured out this is the value present when I change the column to general text.
My question is how can I read the value 12/29/09 instead of 40176 or how can I change 40176 into a valid date?
My program is in c# Must be read in in c#
Here is sample code of my connection if it helps any.
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
string myPath = #"C:\Test.xls";
excelApp.Workbooks.Open(myPath, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "t", false, false, 0, true, 1, 0);
Microsoft.Office.Interop.Excel.Sheets sheets = excelApp.Worksheets;
Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item(1);
excelApp.Visible = true;
if(((Microsoft.Office.Interop.Excel.Range)excelApp.Cells[r, 1]).Value2 != null)
DateString = ((Microsoft.Office.Interop.Excel.Range)excelApp.Cells[r, 1]).Value2.ToString();
You can use DateTime.FromOADate() to convert the double into a DateTime value.
As Reed Copsey said, the DateTime.FromOADate() method will convert the value into a DateTime. If, however, you want 12/29/09 as a string, and don't want to manipulate it any further, you can use cell.Text instead.
Use the excel TEXT(val,format) function.
Example:
In cell A2 enter =today() and you'll get a number like 40189
if you enter into cell A2
If you enter =TEXT(today(),"mm/dd/yyyy") you'll get todays date formatted as text and it will look like "01/30/2012"
you could use the Text function.
Syntax
Text(Value,FormatText)
Example
1)I put the 40176 in a excel A2
2)then i refrence it in the formula below
=TEXT(A2,"mm/dd/yy")
on A3
Then the value comes 12/29/09. just like you asked
Caution:
If you put single quote instead of double quote it mightn't work
Related
I tried to set NumberFormat in a column:
_worksheet.Columns[index].NumberFormat = "#,##0.00";
but I have the result (custom format):
This is similar to recorded macro in the Excel VBA:
Columns(25).NumberFormat = "#,##0.00"
and I have the result (numeric format):
Where is the problem in my first code?
How to set the numeric format?
I have the MS Excel 2016.
EDIT:
When I try to write the number in a formated cell, I have the view:
When I record setup format which I setup by VS, I have the result:
Selection.NumberFormat = "#.##0\.00"
Based on my test, your code can set the numeric format successfully.
Also, I find that you can use NumberFormatLocal to set the format.
Here is a code example you can refer to.
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application application = new Excel.Application();
Excel.Workbook workbook = application.Workbooks.Open("E:\\1.xlsx");
Excel.Worksheet worksheet = workbook.Worksheets[1];
worksheet.Columns[1].NumberFormat = "#,##0.00";
worksheet.Columns[2].NumberFormatLocal= "#,##0.00";
workbook.Save();
workbook.Close();
You can see the following result:(123.456 ->123.46 ;456.789->456.79 and format is
Number)
I have written an application which writes content into an Excelsheet. So far so good. But in some cases the autoformat function from Excel changed my values.
For example, I write 'true'/'false' to a cell, but Excel interprets it and translate it.
Second example, I write a telephonenumber to Excel and Excel cuts the leading '0', so '012345' changed to '12345'.
How can I say, that a cell is just a text/string cell?
This is a samplecode, how I write to Excel:
ws.get_Range("A1", "A1").Value = "true";
ws.get_Range("A1", "A1").Cells.WrapText = true;
ws.get_Range("A1", "A1").Rows.AutoFit();
best regards
Another way to make Excel treat values as text is to add ' in front of the values:
ws.get_Range("A1").Value = "'0123";
The ' will be visible only in the cell formula but not in it's value/text.
You can also set multiple cells at once:
object[,] values = { { "true", "0123" }, { "false", "0125" } };
var range = ws.get_Range("A1:B2")
range.NumberFormat = "#"; // Text format to treat the values as Text
range.Value = values
or
Clipboard.SetText("'true\t'01234\n'false\t'01235");
ws.get_Range("A1").PasteSpecial(); // or just ws.Paste();
Try this for leading zero
ws.get_Range("A1", "A1").NumberFormat = "#";
ws.get_Range("A1", "A1").Value = "012345";
For boolean value
ws.get_Range("B1", "B1").Value = "True/False";
I would like to add a data validation for a cell in an excel to allow ONLY numeric values.
My code does the following,
SpreadSheetGearHelper hlpr = new SpreadSheetGearHelper(excelFilePath);
cells = workbook.Worksheets[0].Cells;
hlpr.WorkSheet(0).Cells[string.Format("{0}:{0}", colName)].Validation.Add(SpreadsheetGear.ValidationType.WholeNumber, ValidationAlertStyle.Stop,
ValidationOperator.Between, "-9999999", "9999999");
hlpr.WorkSheet(0).Cells[string.Format("{0}:{0}", colName)].NumberFormat = "#";
hlpr.WorkSheet(0).Cells[string.Format("{0}:{0}", colName)].Validation.ErrorMessage = "Please enter a number";
But when I enter valid number within the range in excel it still says "Please enter a number".
Can someone please help me out with this
You're currently using the ValidationType.WholeNumber, which will only allow whole numbers such as 1, 2, 3 and not decimals such as 1.23. If you need to allow all numeric values and not just whole numbers you need to specify ValidationType.Decimal. Example:
using SpreadsheetGear;
...
IWorkbook workbook = Factory.GetWorkbook();
IWorksheet worksheet = workbook.ActiveWorksheet;
IRange cells = worksheet.Cells;
cells["A1"].Validation.Add(ValidationType.Decimal, ValidationAlertStyle.Stop,
ValidationOperator.Between, "-9999999", "9999999");
Take a look at this: Apply-Data-Validation-to-Excel-Cells-in-Csharp - CodeProject
sheet.Range["C9"].DataValidation.AllowType = CellDataType.Decimal;
sheet.Range["C9"].DataValidation.Formula1 = "-9999999";
sheet.Range["C9"].DataValidation.Formula2 = "9999999";
sheet.Range["C9"].DataValidation.CompareOperator = ValidationComparisonOperator.Between;
sheet.Range["C9"].DataValidation.InputMessage = "Type a number between -9999999-9999999 in this cell.";
I am not familar with SpreadsheetGear but the solution in this article works fine at my side.
Fixed it.
The Number Format of the cell was set to text, and that was why it was giving me an error every time I had entered a number (Even though the data validation was set correctly). Hence I added the below line of code to change it to "General"
hlpr.WorkSheet(0).Cells[string.Format("{0}:{0}", colName)].NumberFormat = "General";
Thank you guys for your time and responses.
I have an Excel Sheet where I've named the cells I have to fill from my code.
The reason for the named fields is that the customer has the possibility to re-arrange the cells.
To make it a little clearer: I used the field shown below to name the cells.
My problem is now that I have no idea how to address these fields from C# using office interop.
Range r = Sheet.get_Range("M_Leitung", Type.Missing);
doesn't work. Since I don't have any ranges defined, just single cells where I have to insert the values, I'd need a function that returns the named cell.
I just simulated your scenario and the following code worked like a charm (where I labeled A1 in sheet2 as M_Leitung):
Edit: updated code - When you have multiple sheets, you need to refer the names at workbook scope which will return fully qualified address (and hence the resulting range knows which sheet to pick the address from)
private static void Main(string[] args)
{
string FileName = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Book2.xlsx");
Application excelApp = new Application();
Workbooks excelWorkbooks = excelApp.Workbooks;
Workbook report = excelWorkbooks.Open(FileName, 0, false, 5, "", "", true, XlPlatform.xlWindows, "", true, false, 0, false, false, false);
var y = report.Names.Item("M_Leitung").RefersToRange.Value;
Console.WriteLine(y);
excelWorkbooks.Close();
excelApp.Quit();
}
Note that you do create a named range automatically when you rename a cell. If you created a range of say A1:B1 and you selected that. Excel would show you the named range in that corner label rather than the addresses which proves it works both ways.
HTH
Defined Names in Excel have scope, either Workbook or Sheet (ie Global or Local). Typing them in like you've done creates them as Workbook scope. Use the Name Manager to check scope.
Use the Names & RefersToRange properties, not Range to access them. The syntax is slightly different:
Workbook scope: Workbook.Names("M_Leitung").RefersToRange.Value
Worksheet scope: Workbook.Sheet.Names("M_Leitung").RefersToRange.Value
The reason for this is so you can create the same Name on different sheets.
Excel.Application app = new Excel.ApplicationClass();
Excel.Workbook book = app.Workbooks.Open(Filename: System.IO.Path.Combine( Environment.CurrentDirectory, "Book1.xls"));
Excel.Name MyRange = book.Names.Item(Index:"MyRange");
Console.WriteLine(MyRange.RefersToRange.Value);
MyRange.RefersToRange.Value = "55";
book.Save();
app.Quit();
Above code open a file and get the value from workbook and update the range. I think this will solve the problem.
I am losing the leading zeros when I copy values from a datatable to an Excel sheet. That's because probably Excel treats the values as a number instead of text.
I am copying the values like so:
myWorksheet.Cells[i + 2, j] = dtCustomers.Rows[i][j - 1].ToString();
How do I format a whole column or each cell as Text?
A related question, how to cast myWorksheet.Cells[i + 2, j] to show a style property in Intellisense?
Below is some code to format columns A and C as text in SpreadsheetGear for .NET which has an API which is similar to Excel - except for the fact that SpreadsheetGear is frequently more strongly typed. It should not be too hard to figure out how to convert this to work with Excel / COM:
IWorkbook workbook = Factory.GetWorkbook();
IRange cells = workbook.Worksheets[0].Cells;
// Format column A as text.
cells["A:A"].NumberFormat = "#";
// Set A2 to text with a leading '0'.
cells["A2"].Value = "01234567890123456789";
// Format column C as text (SpreadsheetGear uses 0 based indexes - Excel uses 1 based indexes).
cells[0, 2].EntireColumn.NumberFormat = "#";
// Set C3 to text with a leading '0'.
cells[2, 2].Value = "01234567890123456789";
workbook.SaveAs(#"c:\tmp\TextFormat.xlsx", FileFormat.OpenXMLWorkbook);
Disclaimer: I own SpreadsheetGear LLC
If you set the cell formatting to Text prior to adding a numeric value with a leading zero, the leading zero is retained without having to skew results by adding an apostrophe. If you try and manually add a leading zero value to a default sheet in Excel and then convert it to text, the leading zero is removed. If you convert the cell to Text first, then add your value, it is fine. Same principle applies when doing it programatically.
// Pull in all the cells of the worksheet
Range cells = xlWorkBook.Worksheets[1].Cells;
// set each cell's format to Text
cells.NumberFormat = "#";
// reset horizontal alignment to the right
cells.HorizontalAlignment = XlHAlign.xlHAlignRight;
// now add values to the worksheet
for (i = 0; i <= dataGridView1.RowCount - 1; i++)
{
for (j = 0; j <= dataGridView1.ColumnCount - 1; j++)
{
DataGridViewCell cell = dataGridView1[j, i];
xlWorkSheet.Cells[i + 1, j + 1] = cell.Value.ToString();
}
}
Solution that worked for me for Excel Interop:
myWorksheet.Columns[j].NumberFormat = "#"; // column as a text
myWorksheet.Cells[i + 2, j].NumberFormat = "#"; // cell as a text
This code should run before putting data to Excel. Column and row numbers are 1-based.
A bit more details. Whereas accepted response with reference for SpreadsheetGear looks almost correct, I had two concerns about it:
I am not using SpreadsheetGear. I was interested in regular Excel
communication thru Excel interop without any 3rdparty libraries,
I was searching for the way to format column by number, not using
ranges like "A:A".
Before your write to Excel need to change the format:
xlApp = New Excel.Application
xlWorkSheet = xlWorkBook.Sheets("Sheet1")
Dim cells As Excel.Range = xlWorkSheet.Cells
'set each cell's format to Text
cells.NumberFormat = "#"
'reset horizontal alignment to the right
cells.HorizontalAlignment = Excel.XlHAlign.xlHAlignRight
I've recently battled with this problem as well, and I've learned two things about the above suggestions.
Setting the numberFormatting to # causes Excel to left-align the value, and read it as if it were text, however, it still truncates the leading zero.
Adding an apostrophe at the beginning results in Excel treating it as text and retains the zero, and then applies the default text format, solving both problems.
The misleading aspect of this is that you now have a different value in the cell. Fortuately, when you copy/paste or export to CSV, the apostrophe is not included.
Conclusion: use the apostrophe, not the numberFormatting in order to retain the leading zeros.
Use your WorkSheet.Columns.NumberFormat, and set it to string "#", here is the sample:
Excel._Worksheet workSheet = (Excel._Worksheet)_Excel.Worksheets.Add();
//set columns format to text format
workSheet.Columns.NumberFormat = "#";
Note: this text format will apply for your hole excel sheet!
If you want a particular column to apply the text format, for example, the first column, you can do this:
workSheet.Columns[0].NumberFormat = "#";
or this will apply the specified range of woorkSheet to text format:
workSheet.get_Range("A1", "D1").NumberFormat = "#";
if (dtCustomers.Columns[j - 1].DataType != typeof(decimal) && dtCustomers.Columns[j - 1].DataType != typeof(int))
{
myWorksheet.Cells[i + 2, j].NumberFormat = "#";
}
I know this question is aged, still, I would like to contribute.
Applying Range.NumberFormat = "#" just partially solve the problem:
Yes, if you place the focus on a cell of the range, you will read text in the format menu
Yes, it align the data to the left
But if you use the type formula to check the type of the value in the cell, it will return 1 meaning number
Applying the apostroph behave better. It sets the format to text, it align data to left and if you check the format of the value in the cell using the type formula, it will return 2 meaning text
//where [1] - column number which you want to make text
ExcelWorksheet.Columns[1].NumberFormat = "#";
//If you want to format a particular column in all sheets in a workbook - use below code. Remove loop for single sheet along with slight changes.
//path were excel file is kept
string ResultsFilePath = #"C:\\Users\\krakhil\\Desktop\\TGUW EXCEL\\TEST";
Excel.Application ExcelApp = new Excel.Application();
Excel.Workbook ExcelWorkbook = ExcelApp.Workbooks.Open(ResultsFilePath);
ExcelApp.Visible = true;
//Looping through all available sheets
foreach (Excel.Worksheet ExcelWorksheet in ExcelWorkbook.Sheets)
{
//Selecting the worksheet where we want to perform action
ExcelWorksheet.Select(Type.Missing);
ExcelWorksheet.Columns[1].NumberFormat = "#";
}
//saving excel file using Interop
ExcelWorkbook.Save();
//closing file and releasing resources
ExcelWorkbook.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(ExcelWorkbook);
ExcelApp.Quit();
Marshal.FinalReleaseComObject(ExcelApp);
You need to format the column to be a string.
You can use the link https://supportcenter.devexpress.com/ticket/details/t679279/import-from-excel-to-gridview
For converting the ExcelDataSource, you can also refer to https://supportcenter.devexpress.com/ticket/details/t468253/how-to-convert-exceldatasource-to-datatable