string automatically converted in spring - excel

I'm working on a project in Spring using SpringMVC. I'm importing data from (.xls) files .
the problem is that:
I'm reading this value "945854955" as a String but saved in DB as "9.45854955E8"
this value "26929" saved as "26929.0"
this value "21/05/1987" saved as "31918.0"
/read Code
// import ...
#RequestMapping(value="/read")
public String Read(Model model,#RequestParam CommonsMultipartFile[] fileUpload)
throws IOException, EncryptedDocumentException, InvalidFormatException {
List<String> liste = new ArrayList();
Employe employe = new Employe();
String modelnom = null;
liste = extraire(modelnom); //See the second code
for (int m=0, i=29;i<liste.size();i=i+29) {
if(i % 29 == 0) {
m++;
}
employe.setNomEmploye(liste.get(29*m+1));
//...
employe.setDateNaissance((String)liste.get(29*m+8).toString()); // here i had the date problem
employe.setDateEntree((String)liste.get(29*m+9).toString()); // here i had the date problem
employe.setDateSortie((String)liste.get(29*m+10).toString()); // here i had the date problem
// ...
employe.setNumCpteBanc(liste.get(29*m+17)); // here i had the first & second case problem
employe.setNumCIMR(liste.get(29*m+19)); // here i had the first & second case problem
employe.setNumMUT(liste.get(29*m+20)); // here i had the first & second case problem
employe.setNumCNSS(liste.get(29*m+21)); // here i had the first & second case problem
boolean bool=true;
List<Employe> employes = dbE.getAll();// liste des employes
for (int n=0;n<employes.size();n++) {
if (employes.get(n).getMatriculeMY() == (int)mat ) {
bool= false;
}
}
if (bool) {
dbE.create(employe);
}
}
return "redirect";
}
extraire code
private List<String> extraire (String nomFichier) throws IOException {
List<String> liste = new ArrayList();
FileInputStream fis = new FileInputStream(new File(nomFichier));
HSSFWorkbook workbook = new HSSFWorkbook(fis);
HSSFSheet spreadsheet = workbook.getSheetAt(0);
Iterator < Row > rowIterator = null;
// recup une ligne
rowIterator = spreadsheet.iterator();
while (rowIterator.hasNext()) {
int i = 0;
row = (HSSFRow) rowIterator.next();
Iterator < Cell > cellIterator = row.cellIterator();
while ( cellIterator.hasNext()) {
Cell cell = cellIterator.next();
i++;
/**
* Pour verifier si une ligne est vide. (for verifing if the line is empty)
*/
if (i % 29 == 0 || i == 1) {
while ( cellIterator.hasNext() && cell.getCellType() == Cell.CELL_TYPE_BLANK) {
cell = cellIterator.next();
}
}
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
String cellule = String.valueOf(cell.getNumericCellValue());
liste.add(cellule);
break;
case Cell.CELL_TYPE_STRING:
liste.add(cell.getStringCellValue());
break;
case Cell.CELL_TYPE_BLANK:
cellule = " ";
liste.add(cellule);
break;
}
}
}
fis.close();
return liste;
}
}

Excel's tries to data type cells and sometimes when you explicitly specify the data type Excel may try and cast the cell. You can try to right click on the cell and select 'Format Cell', then select 'Text' as the type (Category). However, at parse time it may still get hosed up.
Your quickest solution might be to save the file as a CSV and use that. You can still edit it in Excel. Although you will need to do some validation to ensure Excel isn't trying to do the above conversions on CSV save as. There are a lot of good Java CSV parsers out there OpenCSV, Super CSV.
The most time consuming, but probably the most correct way, if you want to continue to use Excel, is build a middle ware layer that parses the row and correctly identifies and formats the cell values. Apache POI and HSSF & XSSF can be used. Be warned that to handle xls and xlsx requires two different sets of libraries and often enough abstraction to handle both.
See https://poi.apache.org/spreadsheet/
As an Example:
protected String getCellValue(final Cell cell){
if (null == cell) { return null; }
// For Excel binaries 97 and below, The method of setting the cell type to CELL_TYPE_STRING converts the
// Formatted to date to a short. To correct this we check that the cell type is numeric and the check that it is
// date formatted. If we don't check that it is Numeric first an IllegalAccessorException is thrown.
if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC && isCellDateFormated(cell) {
// isCellDateFormated is seperate util function to look at the cell value in order to determine if the date is formatted as a double.
// is a date format.
return // do date format procedure.
}
cell.setTypeCell(Cell.CELL_TYPE_STRING);
return cell.toString();
}
Hope this helps.
============Update==================
Instead of calling methods like "getNumericCellValue()" try setting the cell type to String and using toString like the example above. Here is my test code.
Note the xls file has one row and 4 cells in csv: "abba,1,211,q123,11.22"
public void testExtract() throws Exception{
InputStream is = new FileInputStream("/path/to/project/Test/src/test/java/excelTest.xls");
HSSFWorkbook wb = new HSSFWorkbook(is);
HSSFSheet sheet = wb.getSheetAt(0);
Iterator<Row> rowIter = sheet.iterator();
while (rowIter.hasNext()){
HSSFRow row = (HSSFRow) rowIter.next();
Iterator<Cell> cellIter = row.cellIterator();
while (cellIter.hasNext()){
Cell cell = cellIter.next();
System.out.println("Raw to string: " + cell.toString());
// Check for data format here. If you set a date cell to string and to string the response the output is funky.
cell.setCellType(Cell.CELL_TYPE_STRING);
System.out.println("Formatted to string: " + cell.toString());
}
}
is.close();
}
Output is
Raw to string: abba
Formatted to string: abba
Raw to string: 1.0
Formatted to string: 1
Raw to string: 211.0
Formatted to string: 211
Raw to string: q1123
Formatted to string: q1123
Raw to string: 11.22
Formatted to string: 11.22

Related

How do I read cell value from Excel sheet based on the cell attribute (keyword) using Apache POI integration for Selenium

Example of Excel Data
I need to read the above Example Data using cell reference attribute (highlighted in blue)
The table in the sheet is maintained in column order.
For example, if the table is something like:
firstName
Nick
Jack
lastName
Fury
Ryan
personalEmail
nick-fury#example.com
jack-ryan#example.com
Then I want the script to run for:
firstName
Nick
lastName
Fury
personalEmail
nick-fury#example.com
And then run for:
firstName
Jack
lastName
Ryan
personalEmail
jack-ryan#example.com
And be accessible using the corresponding attributes (firstName, lastName, personalEmail) in my code for the ExcelReader class.
Here's what I want to know:
Is there a way to achieve this using Apache-poi extension for Java?
What function libraries can I used from the apache-poi extension?
What code should I use in my utilities package?
Thanks in Advance :)
To solve this you need to reverse the data getting logic.
So here we first need to get the column data and then traverse all its row.
ie. Nick -> Fury -> nick-fury#example.com and then moving to another column and fetch Jack -> Ryan -> jack-ryan#example.com
Screenshot:
Important Note:
This code is to fetch xls file data using POI, kindly change the code as
per your requirement.
(1). HSSFWorkbook: This class has methods to read
and write Microsoft Excel files in .xls format.
(2).XSSFWorkbook: This class has methods to read and write Microsoft
Excel and OpenOffice xml files in .xls or .xlsx format.
Code:
#Test(dataProvider = "getExcelData")
public void testSheet(String firstName, String lastName, String personalEmail) {
System.out.println(firstName+" "+lastName+" "+personalEmail);
}
#DataProvider
public Object[][] getExcelData(){
String excelSheetPath = System.getProperty("user.dir")+"/data.xls";
String sheetName = "Sheet1";
return getExcelData(excelSheetPath, sheetName);
}
public Object[][] getExcelData(String excelSheetPath, String sheetName) {
Object[][] arrayExcelData = null;
try (
FileInputStream fileStream = new FileInputStream(excelSheetPath)
) {
HSSFWorkbook workbook = new HSSFWorkbook(fileStream);
HSSFSheet sheet = workbook.getSheet(sheetName);
Row row = sheet.getRow(0);
int lastRowIndex = sheet.getLastRowNum() + 1;
System.out.println("Last row index :" + lastRowIndex);
int totalNoOfCols = row.getLastCellNum() - 1;
System.out.println("Total columns :" + totalNoOfCols);
arrayExcelData = new Object[totalNoOfCols][lastRowIndex];
DataFormatter df = new DataFormatter();
for (int i = 1; i <= totalNoOfCols ; i++) {
for (int j = 0; j < lastRowIndex; j++) {
row = sheet.getRow(j);
Cell c = row.getCell(i);
String cellData = df.formatCellValue(c);
System.out.println(cellData);
arrayExcelData[i-1][j] = cellData;
}
System.out.println("-----------");
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
return arrayExcelData;
}

Selenium datadriven testing - unable to fetch the data from the Numbers application (macOS)

I am trying to fetch the data from the Numbers application in macOS, In below code is not able to fetch the value from the cell.
public class Excel {
public static String getdata(String sheetname, int rowvalue, int cellvalue)
{
String value = "";
try {
FileInputStream fis = new FileInputStream("./Excel/Logincred.xlsx");
Workbook wb = WorkbookFactory.create(fis);
Sheet sh = wb.getSheet(sheetname);
Row r = sh.getRow(rowvalue);
Cell c = r.getCell(cellvalue);
value = c.toString();
}
catch(Exception e)
{
}
return value;
}
}
You need to append ' before each number in your excel sheet and then your code would work completely fine.
So lets say, you have a value 4 in your excel, you need to change it to '4 and then your read from excel would work

apache poi write HH:mm:ss string to Excel Time data type

i used apache poi to rewrite a CSV file to Excel, for any string like HH:mm:ss, i need to convert it to the appropriate Excel data type so that user can apply sum() function on that column. i tried different datatype, but when i open the excel file i cannot sum that column the sum always showed as "0:00:00", even though clicking on that column in excel it showed as 'Time' data type,
here is my code:
CreationHelper creationHelper = workbook.getCreationHelper();
HSSFCellStyle timeStyle = workbook.createCellStyle();
timeStyle.setDataFormat(creationHelper.createDataFormat().getFormat("h:mm:ss"));
cell.setCellValue(column);
if (isTime(column)) {
cell.setCellStyle(timeStyle);
}
private boolean isTime(String value) {
try {
dtf.parseDateTime(value);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
and here is my excel file
If the object column in your code is String, then the content of the cell will always be string (text) cell content after cell.setCellValue(column). This content the function SUM cannot work with. Those functions needs numeric content. In Excel date and time also is numeric content only formatted as date-time. With default settings 1 = 1 day = 01/01/1900 00:00:00. 1 hour = 1/24, 1 minute = 1/24/60, 1 second = 1/24/60/60.
If column is string of format "HH:MM:SS", then DateUtil.convertTime can be used to convert this string into a Excel valuable time.
Complete example which shows what not works and what works:
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.DateUtil;
public class ExcelCalculateTimeValues {
public static void main(String[] args) throws Exception {
Workbook workbook = new HSSFWorkbook();
//Workbook workbook = new XSSFWorkbook();
CreationHelper createHelper = workbook.getCreationHelper();
CellStyle styletime = workbook.createCellStyle();
styletime.setDataFormat(createHelper.createDataFormat().getFormat("hh:mm:ss"));
Sheet sheet = workbook.createSheet();
sheet.createRow(0).createCell(0).setCellValue("Time sting");
sheet.getRow(0).createCell(1).setCellValue("Time");
String[][] tableData = new String[][]{
{"12:34:00", "22:45:00"},
{"23:45:05", "01:34:40"},
{"08:01:00", "13:23:00"},
{"15:41:12", "23:23:22"}
};
int r = 1;
for (String[] rowData : tableData) {
Row row = sheet.createRow(r++);
int c = 0;
for (String cellData : rowData) {
Cell cell = row.createCell(c);
if (c == 0 ) {
cell.setCellValue(cellData); //this sets string cell data
} else if (c == 1) {
cell.setCellValue(DateUtil.convertTime(cellData)); //this sets datetime cell data
}
cell.setCellStyle(styletime);
c++;
}
}
sheet.createRow(r).createCell(0).setCellFormula("SUM(A2:A"+r+")"); //cannot work because of string values in A2:A4
sheet.getRow(r).createCell(1).setCellFormula("SUM(B2:B"+r+")"); //will work
workbook.setForceFormulaRecalculation(true);
if (workbook instanceof HSSFWorkbook) {
workbook.write(new FileOutputStream("ExcelCalculateTimeValues.xls"));
} else if (workbook instanceof XSSFWorkbook) {
workbook.write(new FileOutputStream("ExcelCalculateTimeValues.xlsx"));
}
workbook.close();
}
}

Comparing excel value with console output using selenium web driver

I am storing excel values in 1st array and console output values in 2nd array. Then I am comparing excel value with console output one by one .I have debug code and it stores value proper in arrays. But it always print "FALSE" even if value matches true.
My latest code is given below :
WebDriver driver = new FirefoxDriver();
driver.get("https://www.google.co.in/?gfe_rd=cr&ei=1YaGVMutHcXN8gf39ID4Aw&gws_rd=ssl#q=what+is+software+testing");
java.util.List<WebElement> links = driver.findElements(By.tagName("h3"));
int sizecount = links.size();
System.out.println(sizecount);
//READING DATA FROM EXCEL FROM 1ST COLUMN
FileInputStream input = new FileInputStream("D:\\sel.xls");
int count=0;
HSSFWorkbook wb = new HSSFWorkbook(input);
HSSFSheet sh = wb.getSheet("sheet1");
String exceldata[] = new String[20];
for (int i=0;i<=sh.getLastRowNum();i++)
{
HSSFRow row = sh.getRow(i);
exceldata[i]= row.getCell(count).toString();
System.out.println(exceldata[i]);
}
String linkdata[] = new String[20];
for(int j=1;j<=links.size()-1;j++)
{
linkdata[j] = links.get(j).getText();
System.out.println(linkdata[j]);
}
for(int k=0;k<links.size()-1;k++)
{
if(exceldata==linkdata)
{
System.out.println("TRUE");
}
else
{
System.out.println("FALSE");
}
}
driver.close();
}
}
Note : I have tried with operator == and .equals both.
I've told you few issues in your program, you can modify your program according to that.
Issue 1
When you are storing the value in exceldata and linkdata array, you are taking different index, exceldata array is storing value from index 0 and linkdata is storing value from index 1, so you need to modify your program something like below:
for(int k=0;k<links.size()-1;k++){
if(exceldata[k].trim().equals(linkdata[k+1].trim())){
System.out.println("TRUE");
}else{
System.out.println("FALSE");
}
}
There was one more issue, I've already told you.
You are good to go now.

How do I read data from a spreadsheet using the OpenXML Format SDK?

I need to read data from a single worksheet in an Excel 2007 workbook using the Open XML SDK 2.0. I have spent a lot of time searching for basic guidelines to doing this, but I have only found help on creating spreadsheets.
How do I iterate rows in a worksheet and then iterate the cells in each row, using this SDK?
The other answer seemed more like a meta-answer. I have been struggling with this since using LINQ does work with separated document parts. The following code includes a wrapper function to get the value from a Cell, resolving any possible string lookups.
public void ExcelDocTest()
{
Debug.WriteLine("Running through sheet.");
int rowsComplete = 0;
using (SpreadsheetDocument spreadsheetDocument =
SpreadsheetDocument.Open(#"path\to\Spreadsheet.xlsx", false))
{
WorkbookPart workBookPart = spreadsheetDocument.WorkbookPart;
foreach (Sheet s in workBookPart.Workbook.Descendants<Sheet>())
{
WorksheetPart wsPart = workBookPart.GetPartById(s.Id) as WorksheetPart;
Debug.WriteLine("Worksheet {1}:{2} - id({0}) {3}", s.Id, s.SheetId, s.Name,
wsPart == null ? "NOT FOUND!" : "found.");
if (wsPart == null)
{
continue;
}
Row[] rows = wsPart.Worksheet.Descendants<Row>().ToArray();
//assumes the first row contains column names
foreach (Row row in wsPart.Worksheet.Descendants<Row>())
{
rowsComplete++;
bool emptyRow = true;
List<object> rowData = new List<object>();
string value;
foreach (Cell c in row.Elements<Cell>())
{
value = GetCellValue(c);
emptyRow = emptyRow && string.IsNullOrWhiteSpace(value);
rowData.Add(value);
}
Debug.WriteLine("Row {0}: {1}", row,
emptyRow ? "EMPTY!" : string.Join(", ", rowData));
}
}
}
Debug.WriteLine("Done, processed {0} rows.", rowsComplete);
}
public static string GetCellValue(Cell cell)
{
if (cell == null)
return null;
if (cell.DataType == null)
return cell.InnerText;
string value = cell.InnerText;
switch (cell.DataType.Value)
{
case CellValues.SharedString:
// For shared strings, look up the value in the shared strings table.
// Get worksheet from cell
OpenXmlElement parent = cell.Parent;
while (parent.Parent != null && parent.Parent != parent
&& string.Compare(parent.LocalName, "worksheet", true) != 0)
{
parent = parent.Parent;
}
if (string.Compare(parent.LocalName, "worksheet", true) != 0)
{
throw new Exception("Unable to find parent worksheet.");
}
Worksheet ws = parent as Worksheet;
SpreadsheetDocument ssDoc = ws.WorksheetPart.OpenXmlPackage as SpreadsheetDocument;
SharedStringTablePart sstPart = ssDoc.WorkbookPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
// lookup value in shared string table
if (sstPart != null && sstPart.SharedStringTable != null)
{
value = sstPart.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
}
break;
//this case within a case is copied from msdn.
case CellValues.Boolean:
switch (value)
{
case "0":
value = "FALSE";
break;
default:
value = "TRUE";
break;
}
break;
}
return value;
}
Edit: Thanks #Nitin-Jadhav for the correction to GetCellValue().
The way I do this is with Linq. There are lots of sample around on this subject from using the SDK to just going with pure Open XML (no SDK). Take a look at:
Office Open XML Formats: Retrieving
Excel 2007 Cell Values (uses pure
OpenXML, not SDK, but the concepts
are really close)
Using LINQ to Query Tables in Excel
2007 (uses Open XML SDK, assumes
ListObject)
Reading Data from SpreadsheetML
(probably best "overall introduction"
article)

Resources