I'm using OpenXML to create Microsoft Excel file. I'm trying to insert a double type variable (Example : 4.987456789) into the Excel using
Cell cell = new Cell()
{
CellReference = "A2",
DataType = CellValues.String,
CellValue = new CellValue(Convert.ToString(value))
};
But, when the cell is being made, it's in text form and Excel says "The number in this cell is formatted as text or preceded by an apostrophe." How can format the cell to insert double?
Edit :
Sorry, It's double? type and I follow this tutorial
Using CellValues.Number works fine for me, for example :
double? value = 4.9874567891;
Cell cell2 = new Cell()
{
CellReference = "A2",
DataType = CellValues.Number,
CellValue = new CellValue(Convert.ToString(value))
};
Double value printed to excel without the warning you got.
I had the same problem. I followed the advices from the various posts and answers applying a style on the cell... no success.
Finally I found the origin of the problem and so the solution :
In my loop, I inserted all data in the same way i.e. using the InsertSharedStringItem() function.
If you insert a number in your spreadsheet like that, the cell formating will be useless and your number will not be considered as a number.
What you should do is to insert it "directly".
index =InsertSharedStringItem(myStringNumber, shareStringPart);
cell = InsertCellInWorksheet("A", 1, worksheetPart);
cell.CellValue = new CellValue(index.ToString());
cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
cell.StyleIndex = _doubleStyleId;
will not work.
cell = InsertCellInWorksheet("A", 1, worksheetPart);
cell.CellValue = new CellValue(myStringNumber);
cell.DataType = new EnumValue<CellValues>(CellValues.Number);
cell.StyleIndex = _doubleStyleId;
is OK
with as Claies wrote :
Stylesheet styleSheet = workbook.WorkbookStylesPart.Stylesheet;
_doubleStyleId = createCellFormat(styleSheet, null,null, UInt32Value.FromUInt32(4));
the code for createCellFormat() can be found here
OpenXML always creates a cell as Inline Text, and relies upon formatting to determine the correct display format within Excel. Each number format in Excel corresponds to a unique code, and a style can be applied to the cell, the same way you might change the style from within Excel.
The OpenXML Standard defines a series of codes which can be assigned without creating a custom StyleSheet.
The implied format for a double is 4 #,##0.00
so first you create the styleId:
Stylesheet styleSheet = workbook.WorkbookStylesPart.Stylesheet;
_doubleStyleId = createCellFormat(styleSheet, null, null, UInt32Value.FromUInt32(4));
then, set the styleId on the cell:
cell.StyleIndex = _doubleStyleId;
Super late to this party but I ran into this problem and to me the solution was in the default stringifying of my local language, presumably the use of ',' as a decimal delimiter
Cell cell = new Cell() {
DataType = CellValues.Number,
CellValue = new CellValue(value.ToString(new CultureInfo("en-US"))) };
solved it for me.
Related
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
This seems silly, but I haven't been able to get my values in the format of #/#### to write as the literal string rather than becoming formatted as a date within excel.
I'm using ClosedXML to write to excel, and using the following:
// snip
IXLRangeRow tableRow = tableRowRange.Row(1);
tableRow.Cell(1).DataType = XLCellValues.Text;
tableRow.Cell(1).Value = "2/1997";
// snip
Looking at the output excel sheet I get in the cell 2/1/1997 - even though I'm setting the format as text in code, I'm getting it as a "Date" in the excel sheet - I checked this by right clicking the cell, format cell, seeing "date" as the format.
If I change things up to:
// snip
IXLRangeRow tableRow = tableRowRange.Row(1);
tableRow.Cell(1).Value = "2/1997";
tableRow.Cell(1).DataType = XLCellValues.Text;
// snip
I instead get 35462 as my output.
I just want my literal value of 2/1997 to be displayed on the worksheet. Please advise on how to correct.
try this
ws.Cell(rowCounter, colCounter).SetValue<string>(Convert.ToString(fieldValue));
Not sure about from ClosedXML, but maybe try Range.NumberFormat (MSDN Link)
For example...
Range("A1").NumberFormat = "#"
Or
Selection.NumberFormat = "#/####"
Consider:
tableRow.Cell(1).Value = "'2/1997";
Note the single quote.
ws.Cell(rowCounter, colCounter).Value="'"+Convert.ToString(fieldValue));
Formatting has to be done before you write values to the cells.
I had following mechanism, run after I make worksheet, right before I save it:
private void SetColumnFormatToText(IXLWorksheet worksheet)
{
var wholeSheet = worksheet.Range(FirstDataRowIndexInExcel, StartCellIndex, RowCount, HeaderCount);
wholeSheet.Style.NumberFormat.Format = "#";
}
which didn't do squat.
Doing it before I write values to the cells in a row did it.
worksheet.Range(RowIndex, StartCellIndex, RowIndex, EndCellIndex).Style.NumberFormat.Format = "#";
with cell value assignments following immediately after.
I want to colourise my amino acids 1 letter codes automatically from the c# from which they are currently output.
The spreadsheet is output correctly and I have a column such as this example:
A B
1 KJAGLKJGKASLJG
2 FLFSFHDSHDSHHF
3 KJSDALKDJKLFJK
4 KLFDJSHASDFFSD
Every distinct character will be assigned its own colour. For example, K would be Red, L would be Yellow, and D would be Orange. This must be done with the Open XML SDK and not Excel COM programming or a VBA script.
At the moment, this is how the cells are output, but they use the default style sheet.
string columnName = AlphabetLetterRollOver((int) columnIndex);
string cellRef = columnName + (rowIndex + 1);
Cell cell1 = new Cell {CellReference = cellRef, StyleIndex = 1U};
cell1.DataType = CellValues.String;
CellValue cellValue1 = new CellValue();
cellValue1.Text = columnValue;
cell1.Append(cellValue1);
row1.Append(cell1);
I tried the following code as a test case to achieve what I want, but it did not work; it throws an exception:
RunProperties runProperties = new RunProperties();
FontSize fontSize = new FontSize() {Val = 10D};
Color color = new Color() {Rgb = "FF000000"};
RunFont runFont = new RunFont() {Val = "Consolas"};
FontFamily fontFamily = new FontFamily() {Val = 3};
runProperties.Append(fontSize);
runProperties.Append(color);
runProperties.Append(runFont);
runProperties.Append(fontFamily);
Run run = new Run();
Text text = new Text();
text.Text = "A";
run.Append(runProperties);
run.Append(text);
cell1.Append(run);
row1.Append(cell1);
This exception thrown is as follows:
Exception: System.InvalidOperatioonException
Message: Cannot insert the OpenXmlElement "newChild" because it is part of a tree.
Source: DocumentFormat.OpenXml
StrackTrace: at DocumentFormat.OpenXml.OpenXmlCompositeElement.AppendChild[T](T newChild)
at DocumentFormat.OpenXml.OpenXmlElement.Append(OpenXmlElement[] newChildren)
Any ideas will be appreciated, thanks!
What you need to do is create shared strings with each letter set to color you need. Then append as many of them to cells you want.
EDIT -
Download OpenXMLSDKToolV25.msi
Now here is the trick, OpenXML productivity tool is the one you need here. It allows you to brows an existing Excel file and break it down to CODES : watch
Now what you need to do is create an Excel sheet manually with what you want [In your case having multi colur text] Then open this Excel file with productivity tool and understand the CODE . Note that you will need to understand Spreadsheet file structure to understand this CODE [ Refer this] .. Now write your codes to meet your requirement using codes of Productivity tool
NOTE - Once you analyse the dummy Spreadsheet with Productivity tool you will understand why giving or guiding with CODE examples as an answer is not practical. Just try with A cell with multicolor texts
I'm using the OpenXML SDK to parse .xlsx files.
When I have very large numbers in the Excel file, i.e. 344230125015305000, OpenXML converts it to the scientific version, i.e. 3.4423012501530502E+17. This is strange, as the "full" value is present in the Excel file, meaning it hasn't been truncated and it should be available somewhere in the Cell object.
Any suggestions are most welcome.
UPDATE:
#AlexeiLevenkov suggested I look at the xml file, and it appears the values are stored in scientific form. Interestingly, Excel still shows the full form.
Examples:
344110425109461000 -> 3.4411042510946099E+17
344230125015305000 -> 3.4423012501530502E+17
344770124807291000 -> 3.4477012480729101E+17
344770224905172000 -> 3.4477022490517197E+17
Attempting to covert back to full form, i.e.
(long)Double.Parse("3.4411042510946099E+17", CultureInfo.InvariantCulture)
returns an incorrect value (344110425109460992 for the above snippet).
Adding a single quote prefix to the value fixes the problem (another indicator, that the full form value is hidden in there somewhere), but it's not a solution for this scenario, as I'm try to build an automated processing of user-uploaded files.
Use Open XML Productivity Tool and reflect the code of your file.
I did, here what the tool provides
public class GeneratedClass
{
// Creates an Cell instance and adds its children.
public Cell GenerateCell()
{
Cell cell1 = new Cell(){ CellReference = "A1", StyleIndex = (UInt32Value)1U };
CellValue cellValue1 = new CellValue();
cellValue1.Text = "3.4411042510946099E+17";
cell1.Append(cellValue1);
return cell1;
}
}
So as you can see large numbers are store only in scientific notation, then you jus need
Double value = Double.Parse("3.4411042510946099E+17",
NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint,
System.Globalization.CultureInfo.InvariantCulture);
The value it will be ok!
The fun fact (Maybe some c# gurus can tell us why) is then you have to convert first to string.
String strdouble = value.ToString("#", System.Globalization.CultureInfo.InvariantCulture);
Int64 conv = Convert.ToInt64(value);
// conv will be: 344110425109460992
Int64 conv1 = Convert.ToInt64(strdouble, System.Globalization.CultureInfo.InvariantCulture);
// conv1 will be: 344110425109461000
Your styles need to be declared like this:
CellStyleFormats cellStyleFormats1 = new CellStyleFormats() { Count = (UInt32Value)1U };
CellFormat cellFormat1 = new CellFormat() { NumberFormatId = (UInt32Value)1U, FontId = (UInt32Value)0U, FillId = (UInt32Value)0U, BorderId = (UInt32Value)0U, ApplyNumberFormat = true };
Notice the NumberFormatId and the ApplyNumberFormat, this ID must be one so that in the XML looks something like this:
<xf numFmtId="1" fontId="0" fillId="0" borderId="0" xfId="0" applyNumberFormat="1"/>
PS:
From MSDN:
https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.numberingformat(v=office.14).aspx
I am trying to create double and number format cells in excel using NPOI library. I used code like
Dim cell As HSSFCell = row.CreateCell(j)
cell.SetCellValue(Double.Parse(dr(col).ToString))
In excel numbers are aligning right but when I check format it is showing in "General"
then I changed my code to like below
Dim cell As HSSFCell = row.CreateCell(j)
cell.SetCellValue(Double.Parse(dr(col).ToString))
Dim cellStyle As HSSFCellStyle = hssfworkbook.CreateCellStyle
cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("#,#0.0")
cell.CellStyle = cellStyle
Then While opening file it is giving error and also taking so long to open. But Excel format showing in "Number"
error showing is like below.
How to fix this?
Take a look at this, are you creating a cellStyle object for each cell? If so don't. Try creating just a couple of styles before creating your cells and then apply these pre-defined styles to the cells you create.
To fix the too many different cell styles declare all styles outside of any loop you may be running.
I'm presumeing you 'j' would be the enumerator so i'll drop what you had in a corrected format for you.
Dim cellStyle As HSSFCellStyle = hssfworkbook.CreateCellStyle
cellStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("#,#0.0")
For col = 0 To ColoumCounter
For j = 0 To Counter
Dim cell As HSSFCell = row.CreateCell(j)
cell.SetCellValue(Double.Parse(dr(col).ToString))
cell.CellStyle = cellStyle
Next
Next
This should work a bit better, by limiting the number of "New" styles.
Hare is a simple way to create double format in Excel Document USING NPOI.
//make NUMERIC Format in Excel Document // Author: Akavrelishvili
var eRow = sheet.CreateRow(rowIndex); //create new Row , rowIndex - it's integer, like : 1,2,3
eRow.CreateCell(0).SetCellValue(row["ProvidName"].ToString()); //create cell and set string value
double Amount = Convert.ToDouble(row["Amount"].ToString()); //convert string to double
eRow.CreateCell(1).SetCellValue(Amount); // create cell and set double value.
This is working version, I have used it a lots of projects.
Very Hard is to insert DateTime format in Excel, There no good example in Internet and I think it helps people to do it right way.
I show you code example:
//make Date Time Format in Excel Document // Author: Akavrelishvili
var eRow = sheet.CreateRow(rowIndex); //create new Row // rowIndex - it's integer, like : 1,2,3
ICellStyle cellDateStyle = workBook.CreateCellStyle(); //create custom style
cellDateStyle.DataFormat = workBook.CreateDataFormat().GetFormat("dd/mm/yyyy"); //set day time Format
eRow.CreateCell(3).SetCellValue(Convert.ToDateTime(row["Date"])); //set DateTime value to cell
eRow.GetCell(6).CellStyle = cellDateStyle; // Restyle cell using "cellDateStyle"
I hope it helps
Create a style then but this style for the column
ICellStyle _TextCellStyle = wb1.CreateCellStyle();
_TextCellStyle.DataFormat = wb1.CreateDataFormat().GetFormat("#");
sheet.SetDefaultColumnStyle(2, _TextCellStyle);