Apache POI : How to format numeric cell values - apache-poi

I am using Apache POI 3.9 for XLS/XLSX file processing.
In the XLS sheet, there is a column with numeric value like "3000053406".
When I read it with POI with..
cell.getNumericCellValue()
It gives me value like "3.00E+08". This create huge problem in my application.
How can I set the number formatting while reading data in Apcahe POI ?
There is a way that I know is to set the column as "text" type. But I want to know if there is any other way at Apache POI side while reading the data. OR can we format it by using simple java DecimalFormatter ?

This one comes up very often....
Picking one of my past answers to an almost identical question
What you want to do is use the DataFormatter class. You pass this a cell, and it does its best to return you a string containing what Excel would show you for that cell. If you pass it a string cell, you'll get the string back. If you pass it a numeric cell with formatting rules applied, it will format the number based on them and give you the string back.
For your case, I'd assume that the numeric cells have an integer formatting rule applied to them. If you ask DataFormatter to format those cells, it'll give you back a string with the integer string in it.

Problem can be strictly Java-related, not POI related, too.
Since your call returns a double,
double val = cell.getNumericCellValue();
You may want to get this
DecimalFormat df = new DecimalFormat("#");
int fractionalDigits = 2; // say 2
df.setMaximumFractionDigits(fractionalDigits);
double val = df.format(val);

Creating a BigDecimal with the double value from the numeric cell and then using the
BigDecimal.toPlainString()
function to convert it to a plain string and then storing it back to the same cell after erasing the value solved the whole problem of exponential representation of numeric values.
The below code solved the issue for me.
Double dnum = cellContent.getNumericCellValue();
BigDecimal bd = new BigDecimal(dnum);
System.out.println(bd.toPlainString());
cellContent.setBlank();
cellContent.setCellValue(bd.toPlainString());
System.out.println(cellContent.getStringCellValue());

long varA = new Double(cellB1.getNumericCellValue()).longValue();
This will bring the exact value in variable varA.

Related

Data extraction from excel with operators is unable to store values

I have a Excel file with two columns. One has a name other has the corresponding mass to it. I have used the corresponding lines to read it and find the position of the name. But when I am trying to find the mass to the corresponding name as shown below it is not able to store it in the memory. In the Excel file, I have the mass values as 1.989*10^30. This seems to affect the code as the same code works fine when the cells in the excel has just numeric values.
majbod = 'Sun';
minbod = 'Earth';
majbodin = readtable("Major_and_Minor_Bodies.xlsx","Sheet",1);
minbodin = readtable("Major_and_Minor_Bodies.xlsx","Sheet",2);
MAJORBODY = table2array(majbodin(:,"Major_Body"));
MINORBODY = table2array(minbodin(:,"Minor_Body"));
mmaj = table2array(majbodin(:,"Mass"));
mmin = table2array(minbodin(:,"Mass"));
selected_majbody = find(strcmp(MAJORBODY,majbod));
selected_minbody = find(strcmp(MINORBODY,minbod));
M = mmaj(selected_majbody);
m = mmin(selected_minbody);
disp([M ;m])
Is there a better way to write the code compared to the way which I wrote?
Thanks.
Excel does it's best to figure out what kind of data is in each cell. Since your data has something besides just numbers, Excel treats it like a string. You have a couple of options for getting around that:
If you put an equals sign in front of it, it will treat it like an equation, and calculate the value of 1.989*10^3 for you. this will be a number.
Since scientific notation is so common, programmers have created a shortcut for representing it. They often use the character 'E' where you use "*10^". This means that if you type "1.989E30", excel will recognize that as a number.
If keeping the current string format is very important, you could probably modify the string during extraction - replace '*10^' with E, and then whatever language you are using will have a string to number parser you can use.
If the real problem is that the real numbers are just too long in Excel, you can always format the cell that they are in. (right click the cell, select format cells, then select scientific.)
Good luck

Changing a numeric to a string variable in Stata

I have a variable ShiftStart that is a numeric variable in the format 01jan2014 06:59:59 (and so on). I want to change this to a string variable so that I can then substring it and create variables based on just date and just time separately.
When I try
generate str20 string_shiftstart=string(ShiftStart)
I create a string but all of the cells have been converted to strange values ("1.70e+12" and so on).
How can I keep the original contents of ShiftStart when it is converted to a string?
It seems you have a variable formatted as datetime. If so, no need to convert to string. There are appropriate functions that allow you to manipulate the original variable. This is clearly explained in help datetime:
clear
set more off
*----- example data -----
set obs 5
gen double datet = _n * 100000000
format datet %tc
list
*----- what you want -----
gen double date = dofc(datet)
format %td date
gen double hour = hh(datet) + mm(datet)/60 + ss(datet)/3600
list
The reason you find your original result surprising is because you are not aware of the fact that underlying the datetime display format, is a numerical value.
A good read (aside from help datetime) is
Stata tip 113: Changing a variable's format: What it does and does not mean, The Stata Journal, by Nicholas J. Cox.
Edit
To answer your last question:
If you want to create an indicator variable marking pre/post periods, one way is using td() (see the help file). Following the example given above:
// before 04jan1960
gen pre = date < td(04jan1960)
Creating this indicator variable is not always necessary. Most commands allow the use of the if qualifier, and you can insert the condition directly. See help if.
If you mean something else, you should be more explicit.

JExcel/POI: Creating a cell as type Text

I have a requirement that involves reading values from an excel spreadsheet, and populating a spreadsheet for users to modify and re-upload to our application. One of these cells contains a text string of 5 characters that may be letters, numbers, or a combination of both. Some of these strings contain only numbers, and begin with a zero. Because of this, the cell type is Text; however, when I use Apache POI or JExcel to populate a spreadsheet for the users to modify it is always set as cell type General.
Is there a way using either of these libraries, or some other excel api that I have not seen yet, to specify that a cell have type Text?
My co-worker just found a way to accomplish this. In JExcel, it can be accomplished by using a WritableCellFormat such as:
WritableCellFormat numberAsTextFormat = new WritableCellFormat(NumberFormats.TEXT);
Then, when you are creating your cell to add to a sheet you just pass in the format as normal:
Label l = new Label(0, 0, stringVal, numberAsTextFormat);
If you are using Apache POI, you would create a HSSFCellStyle, and then set it's data format like this:
HSSFCellStyle style = book.createCellStyle();
style.setDataFormat(BuiltInFormats.getBuiltInFormat("text"));
Many times when user enters number in cell which type(formatting) is text(string), spreadsheet software (openoffice or msoffice) changes it's formatting automatically. I am using apache poi and this is the way I wrote my code :
cell = row.getCell();
switch (cell.getCellType()) {
case HSSFCell.CELL_TYPE_STRING:
value = cell.getRichStringCellValue().getString();
break;
case HSSFCell.CELL_TYPE_NUMERIC:
// if cell fomratting or cell data is Numeric
// Read numeric value
// suppose user enters 0123456 (which is string), in numeric way it is read as 123456.0
// Now I want ot read string and I got number...Problem?????
//well this is the solution
cell.setCellType(Cell.CELL_TYPE_STRING); // set cell type string, so it will retain original value "0123456"
value = cell.getRichStringCellValue().getString(); // value read is now "0123456"
break;
default:
}

Decimal numbers using CarlosAg.ExcelXmlWriter

I would appreciate an answer how to solve the following problem.
I use CarlosAg.ExcelXmlWriter and I have a problem with formatting decimal numbers in Excel.
Example: I have SQL field TestField, Decimal(15,2)) with value 123.45
When i transfer the result (DataSet and some C# routine) into Excel with CarlosAg.ExcelXmlWriter the result is always 12345 - as though Carlos does not recognizes decimal number correctly.
I tried formatting data on SQL side and on Carlos side and result is always concatenated number (123.45 -> 12345)
A a side note - i did sort of "solve" the problem by casting the number into varchar but that is not acceptable for our customer because he can not format strings in the excel (like making SUM etc..) and he wants the Excel field to be explicitly numeric not string.
I am almost shure there is some simple answer for that.
Thanks
Damir
I tried Carlos with NumberFormat :
//style2.NumberFormat = "Scientific";
//style2.NumberFormat = "General Number";
//style2.NumberFormat = "###,###.00";
//style2.NumberFormat = "###.###,00";
...
case "System.Decimal":
case "System.Double":
wc = new WorksheetCell(dtrrow[col.ColumnName].**ToString().Replace(",",".")**, DataType.Number, style_number);
row.Cells.Add(wc);
...

Excel turning my numbers to floats

I have a bit of ASP.NET code that exports data in a datagrid into Excel but I noticed that it messes up a particular field when exporting.
E.g. I have the value of something like 89234010000725515875 in a column in the datagrid but when exported, it turns it into 89234+19.
Is there any Excel formatting that will bring back my original number? Thanks.
Excel isn't really messing up the field. Two things are happening:
Excel formats large numbers in scientific notation. So "89234010000725515875" becomes "8.9234E+19" or "8.9234 x 10 ^ 19".
The size of the number "89234010000725515875" exceeds the precision in which Excel uses to store values. Excel stores your number as "89234010000725500000" so you're losing the last five digits.
Depending on your needs you can do one of two things.
Your first option is to change the formatting from "General" to "0" (Number with zero decimal places.) This will give you "89234010000725500000" so you will have lost precision but you will be able to perform calculcations on the number.
The second option is to format the cell as text "#" or to paste your field with an apostrophe at the beginning of the line to force the value to be text. You'll get all of the digits but you won't be able to do calculations of the value.
I hope this helps.
You can add a space to the field, then when you export it to Excel, it's considered as string:
lblTest.Text = DTInfo.Rows(0).Item("Test") & " "
Good luck.
Below is the C# source code to do this with SpreadsheetGear for .NET. Since the SpreadsheetGear API is similar to Excel's API, you should be able to easily adapt this code to Excel's API to get the same result.
You can download a free trial here if you want to try it yourself.
Disclaimer: I own SpreadsheetGear LLC
using System;
using SpreadsheetGear;
namespace Program
{
class Program
{
static void Main(string[] args)
{
// Create a new workbook and get a reference to A1.
IWorkbook workbook = Factory.GetWorkbook();
IWorksheet worksheet = workbook.Worksheets[0];
IRange a1 = worksheet.Cells["A1"];
// Format A1 as Text using the "#" format so that the text
// will not be converted to a number, and put the text in A1.
a1.NumberFormat = "#";
a1.Value = "89234010000725515875";
// Show that the formatted value is
Console.WriteLine("FormattedValue={0}, Raw Value={1}", a1.Text, a1.Value);
// Save the workbook.
workbook.SaveAs(#"c:\tmp\Text.xls", FileFormat.Excel8);
workbook.SaveAs(#"c:\tmp\Text.xlsx", FileFormat.OpenXMLWorkbook);
}
}
}

Resources