When I read very small values from Excel sheet these are shown as scientific precision. For example, the -0.00002 is always read as -2E05 using Cells().Values function. Below are the conversion lines I have used, without any success. How to get the actual value instead of the scientific format?
var canConvert = decimal.TryParse(ws.Cells[1, 1].Value.ToString(), out _); // result in false
var cellString = ws.Cells[1, 1].Value.ToString("R"); // -2E05
var cellStrin2g = ws.Cells[1, 2].Value.ToString(); // -2E05
It seems you need to set up the required NumberFormat first:
ws.Range("A17").NumberFormat = "General"
The format code is the same string as the Format Codes option in the Format Cells dialog box.
After several trial I have came up to the following solution, which works well in my model.
double number = 0;
var canConvert = double.TryParse(ws.Cells[row, column].Value.ToString(), out number3);
if (canConvert)
string doubleAsString = cell.ToString("F99").TrimEnd('0');
Bear in mind that the above scenario works well upto 99 following digits. Feel free to extend it to your needs.
Related
In my rdlc report have following columns
SlNo, Item, Uom, Qty, Rate, Amount
Here the Amount field is a formula (Rate*Qty)
The report is working fine, and when i export to excel also displaying the values are correctly.
But my problem is, after export to excel, when i change the Qty or Rate columns in excel file the Amount is not get changed automatically, because the formula is missing in the excel cell.
How can we include the formula in Amount column while export to excel from .rdlc?
I'm afraid that this required behaviour isn't really possible by just using the rdlc rendering.
In my search I stumbled upon this same link that QHarr posted: https://social.msdn.microsoft.com/Forums/en-US/3ddf11bf-e10f-4a3e-bd6a-d666eacb5ce4/report-viewer-export-ms-report-data-to-excel-with-formula?forum=vsreportcontrols
I haven't tried the project that they're suggesting but this might possibly be your best solution if it works. Unfortunately I do not have the time to test it myself, so if you test this please share your results.
I thought of the following workaround that seems to work most of the times, but isn't really that reliable because the formula sometimes gets displayed as full-text instead of being calculated. But I guess this could be solved by editing the excel file just after being exported, and changing the cell properties of this column containing the formula or just triggering the calculate.
Using the built-in-field Globals!RenderFormat.Name you can determine the render mode, this way you can display the result correctly when the report is being rendered to something different than Excel. When you export to Excel, you could change the value of the cell to the actual formula.
To form the formula it's self you'll need to figure this out on your own, but the RowNumber(Scope as String) function can be of use here to determine the row number of your cells.
Here is a possible example for the expression value of your amount column
=IIF(Globals!RenderFormat.Name LIKE "EXCEL*", "=E" & Cstr(RowNumber("DataSet1")+2) & "*F" & Cstr(RowNumber("DataSet1")+2) ,Fields!Rate.Value * Fields!Qty.Value )
Now considering that this formula sometimes gets displayed as full-text, and you'll probably have to edit the file post-rendering. If it's too complicated to determine which row/column the cell is on, you could also do this post-rendering. But I believe that the above expression should be easy enough to use to get your desired result without having to do much after rendering.
Update: The following code could be used to force the calculation of the formula (post rendering)
var fpath = #"C:\MyReport.xlsx";
using (var fs = File.Create(fpath))
{
var lr = new LocalReport();
//Initializing your reporter
lr.ReportEmbeddedResource = "MyReport.rdlc";
//Rendering to excel
var fbytes = lr.Render("Excel");
fs.Write(fbytes, 0, fbytes.Length);
}
var xlApp = new Microsoft.Office.Interop.Excel.Application() { Visible = false };
var wb = xlApp.Workbooks.Open(fpath);
var ws = wb.Worksheets[1];
var range = ws.UsedRange;
foreach (var cell in range.Cells)
{
var cellv = cell.Text as string;
if (!string.IsNullOrWhiteSpace(cellv) && cellv.StartsWith("="))
{
cell.Formula = cellv;
}
}
wb.Save();
wb.Close(0);
xlApp.Quit();
I tried to create a file with decimal numbers on cells (F1:F4), but when i am going to insert a formula to the cell, it's show it like a string.
Code:
s1("F5").Formula = "=SUMME(F1:F4)"
s1("F5").Value = s1("F5").Formula
i tried:
s1("F5").Formula = "=SUMME(F1:F4)"
s1("F5").Formatting.HiddenFormula = False
s1("F5").Value = s1("F5").Formula
i tried:
s1("F5").Formula = "=SUMME(F1:F4)"
The result its the same, on cell F5, =SUMME(F1:F4)
always on string format.
Note : s1 = Sheet1
Try this:
s1.Cells("F5").Formula = "=SUM(F1:F4)"
You didn't set the range of the sheet. Also changed the SUMME to SUM, unless you have a User Defined Function (UDF) which is called SUMME or you are using Excel in a language where Summe = Sum.
EDIT:
After looking into the library you are using, I would try the following:
s1["F5"].Value = "=SUMME(F1:F4)";
I found the solution. With that library, it's not possible.
I used another library just to make the formula. Nix library it's good to add data to the cells.
I am want to read excel file having phone numbers stored as numbers but when I read the file using SheetJS/js-xlsx (npm install xlsx), All the large phone numbers are converted to strings like
9.19972E+11
919971692474 --> 9.19972E+11
My code is
var workbook = XLSX.readFile(req.files.fileName.path);
var sheet_name_list = workbook.SheetNames;
var csvFile = XLSX.utils.sheet_to_csv(workbook.Sheets[sheet_name_list[0]]);
console.log(csvFile2);
console output is
customer_phone,product_name
9.19972E+13,"Red Belly Shoes,"
Is there any way I can avoid such conversion?
The number 919971692474 is normally displayed as 9.19972E+11 in Excel. To force it to display the full number you have to set the number format to 0 (right click, format cell, choose custom type '0'). And when you do that, the full number is displayed. If you don't set a format in excel, the xlsx module uses the "General" format and that number format displays the phone number as an exponential.
If the file is incorrect, you can override the CSV formatting by deleting the w key and adding a z key corresponding to the desired number format. For example, to change cell A2:
var sheet = workbook.Sheets[workbook.SheetNames[0]];
delete sheet.A2.w;
sheet.A2.z = '0';
If you want to do this for all number cells, just loop:
Object.keys(sheet).forEach(function(s) {
if(sheet[s].w) {
delete sheet[s].w;
sheet[s].z = '0';
}
});
By default sheet_to_csv take the formatted numbers.
- To avoid the formatted value and to take raw inputs (original values) you have to add parameter in sheet_to_csv method you have to set rawNumbers to true
Try this code
var csvFile = XLSX.utils.sheet_to_csv(workbook.Sheets[sheet_name_list[0]], { rawNumbers: true });
It seems in later versions w is not there. That's how it could be done in recent versions.
const ws = XLSX.utils.json_to_sheet(data);
Object.keys(ws).forEach(function(s) {
if(ws[s].t === 'n') {
ws[s].z = '0';
ws[s].t = 's';
}
});
const csv = XLSX.utils.sheet_to_csv(ws);
Using sheet[s].z = '0'; works in removing the scientific notation, but it also removes any decimal places you might want to retain. From the readme:
The cell.w formatted text for each cell is produced from cell.v and cell.z format.
I was able to remove the scientific notation by explicitly setting the value of w instead of letting xlsx calculate it for me:
if (cell.t === 'n') {
cell.w = cell.v;
}
I've got the value '9,2' (dutch notation of '9.2') within a cell of a .xlsx file, the cell has a 'general' number format. Also the value in the upper bar where you also view formulas says '9,2' When I read this cell with PHPExcel with ->getValue() I get '9,199999999999999'.
This is my code:
$oPhpReader = PHPExcel_IOFactory::createReader($sFileType);
$aWorksheetNames = $oPhpReader->listWorksheetNames($sFileName);
$oPhpReader->setReadDataOnly(true);
$oPhpReader->setLoadSheetsOnly($aWorksheetNames[0]);
$oPhpExcel = $oPhpReader->load($sFileName);
$oWorksheet = $oPhpExcel->getActiveSheet();
$oCell = $oWorksheet->getCellByColumnAndRow($iCol,$iRow);
$sTempValue = $oCell->getValue();
This is the way I solved my problem now. Though I do not think this is a very neat solution, it is probably the only way.
I just figured I will never get numbers with more than 12 digits, only when PHPExcel get them wrong. So I round all my floats to 12 digit using number_format:
if ((is_numeric($sTempValue))&&(strpos($sTempValue,'.')))
{
$sTempValue = rtrim(rtrim(number_format($sTempValue,12,',',''),'0'),',');
}
When I read a sheet into a DataTable using the OleDbDataReader, floating point numbers loose their precision.
I tried forcing OleDb to read the excel data as string, but although the data is now contained in a DataRow with each Column defined as System.String it looses precision (18.125 -> 18.124962832).
Any idea how to avoid this behaviour?
I just tested your data and this method posted here worked.
i.e. the cell value kept it's precision 18.124962832, when put into DataSet.
I'm pretty sure that Jet tries to assign a datatype to each column based on what it sees in the first five rows. If something after those first five rows doesn't fall into that data type it will either convert it or return nothing at all.
Do the first five rows of your spreadsheet have a lower precision than the items that are begin truncated?
Take a look at this post.
The output from the code below shows you how to get the underlying number and the formatted text with SpreadsheetGear for .NET:
Here is the output from the code:
x=18.124962832 y=18.124962832 formattedText=18.125
Here is the code:
namespace Program
{
class Program
{
static void Main(string[] args)
{
// Create a new workbook and get a reference to Sheet1!A1.
var workbook = SpreadsheetGear.Factory.GetWorkbook();
var sheet1 = workbook.Worksheets[0];
var a1 = workbook.Worksheets[0].Cells["A1"];
// Put the number in the cell.
double x = 18.124962832;
a1.Value = x;
a1.NumberFormat = "0.000";
double y = (double)a1.Value;
string formattedText = a1.Text;
System.Console.WriteLine("x={0} y={1} formattedText={2}", x, y, formattedText);
}
}
}
You can see live SpreadsheetGear samples here and download the free trial here.
Disclaimer: I own SpreadsheetGear LLC