I am trying to convert excel data into JSON format. but the problem is I have excel sheets which are linked to multiple excel sheet. like example root.xlsx which contains
id, name, phone,department,category,age fields
and where department field refers to department.xlsx which contains
dname, did, dtype
and category fields refers to category.xlsx which contains
catid,catname,cattype,
how to convert it to JSON if the data format is like this?
Jars Required
commons-beanutils-1.8.3.jar
ezmorph-1.0.6.jar
commons-collections-3.2.1.jar
commons-lang-2.6.jar
json-lib-2.4-jdk15.jar
poi
Sample code
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Header;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openqa.selenium.json.Json;
import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;
import net.sf.json.JSONObject;
public class ReadExcelDataWithDynamicColumn {
public static void main(String[] args)
{
// You can specify your excel file path.
String excelFilePath = "/Users/zhaosong/Documents/WorkSpace/EmployeeInfo.xls";
// This method will read each sheet data from above excel file and create a JSON and a text file to save the sheet data.
creteJSONAndTextFileFromExcel(excelFilePath);
}
/* Read data from an excel file and output each sheet data to a json file and a text file.
* filePath : The excel file store path.
* */
private static void creteJSONAndTextFileFromExcel(String filePath)
{
try{
/* First need to open the file. */
FileInputStream fInputStream = new FileInputStream(filePath.trim());
/* Create the workbook object to access excel file. */
//Workbook excelWookBook = new XSSFWorkbook(fInputStream)
/* Because this example use .xls excel file format, so it should use HSSFWorkbook class. For .xlsx format excel file use XSSFWorkbook class.*/;
Workbook excelWorkBook = new HSSFWorkbook(fInputStream);
// Get all excel sheet count.
int totalSheetNumber = excelWorkBook.getNumberOfSheets();
// Loop in all excel sheet.
for(int i=0;i<totalSheetNumber;i++)
{
// Get current sheet.
Sheet sheet = excelWorkBook.getSheetAt(i);
// Get sheet name.
String sheetName = sheet.getSheetName();
if(sheetName != null && sheetName.length() > 0)
{
// Get current sheet data in a list table.
List<List<String>> sheetDataTable = getSheetDataList(sheet);
// Generate JSON format of above sheet data and write to a JSON file.
String jsonString = getJSONStringFromList(sheetDataTable);
String jsonFileName = sheet.getSheetName() + ".json";
writeStringToFile(jsonString, jsonFileName);
// Generate text table format of above sheet data and write to a text file.
String textTableString = getTextTableStringFromList(sheetDataTable);
String textTableFileName = sheet.getSheetName() + ".txt";
writeStringToFile(textTableString, textTableFileName);
}
}
// Close excel work book object.
excelWorkBook.close();
}catch(Exception ex){
System.err.println(ex.getMessage());
}
}
/* Return sheet data in a two dimensional list.
* Each element in the outer list is represent a row,
* each element in the inner list represent a column.
* The first row is the column name row.*/
private static List<List<String>> getSheetDataList(Sheet sheet)
{
List<List<String>> ret = new ArrayList<List<String>>();
// Get the first and last sheet row number.
int firstRowNum = sheet.getFirstRowNum();
int lastRowNum = sheet.getLastRowNum();
if(lastRowNum > 0)
{
// Loop in sheet rows.
for(int i=firstRowNum; i<lastRowNum + 1; i++)
{
// Get current row object.
Row row = sheet.getRow(i);
// Get first and last cell number.
int firstCellNum = row.getFirstCellNum();
int lastCellNum = row.getLastCellNum();
// Create a String list to save column data in a row.
List<String> rowDataList = new ArrayList<String>();
// Loop in the row cells.
for(int j = firstCellNum; j < lastCellNum; j++)
{
// Get current cell.
Cell cell = row.getCell(j);
// Get cell type.
int cellType = cell.getCellType();
if(cellType == CellType.NUMERIC.getCode())
{
double numberValue = cell.getNumericCellValue();
// BigDecimal is used to avoid double value is counted use Scientific counting method.
// For example the original double variable value is 12345678, but jdk translated the value to 1.2345678E7.
String stringCellValue = BigDecimal.valueOf(numberValue).toPlainString();
rowDataList.add(stringCellValue);
}else if(cellType == CellType.STRING.getCode())
{
String cellValue = cell.getStringCellValue();
rowDataList.add(cellValue);
}else if(cellType == CellType.BOOLEAN.getCode())
{
boolean numberValue = cell.getBooleanCellValue();
String stringCellValue = String.valueOf(numberValue);
rowDataList.add(stringCellValue);
}else if(cellType == CellType.BLANK.getCode())
{
rowDataList.add("");
}
}
// Add current row data list in the return list.
ret.add(rowDataList);
}
}
return ret;
}
/* Return a JSON string from the string list. */
private static String getJSONStringFromList(List<List<String>> dataTable)
{
String ret = "";
if(dataTable != null)
{
int rowCount = dataTable.size();
if(rowCount > 1)
{
// Create a JSONObject to store table data.
JSONObject tableJsonObject = new JSONObject();
// The first row is the header row, store each column name.
List<String> headerRow = dataTable.get(0);
int columnCount = headerRow.size();
// Loop in the row data list.
for(int i=1; i<rowCount; i++)
{
// Get current row data.
List<String> dataRow = dataTable.get(i);
// Create a JSONObject object to store row data.
JSONObject rowJsonObject = new JSONObject();
for(int j=0;j<columnCount;j++)
{
String columnName = headerRow.get(j);
String columnValue = dataRow.get(j);
rowJsonObject.put(columnName, columnValue);
}
tableJsonObject.put("Row " + i, rowJsonObject);
}
// Return string format data of JSONObject object.
ret = tableJsonObject.toString();
}
}
return ret;
}
/* Return a text table string from the string list. */
private static String getTextTableStringFromList(List<List<String>> dataTable)
{
StringBuffer strBuf = new StringBuffer();
if(dataTable != null)
{
// Get all row count.
int rowCount = dataTable.size();
// Loop in the all rows.
for(int i=0;i<rowCount;i++)
{
// Get each row.
List<String> row = dataTable.get(i);
// Get one row column count.
int columnCount = row.size();
// Loop in the row columns.
for(int j=0;j<columnCount;j++)
{
// Get column value.
String column = row.get(j);
// Append column value and a white space to separate value.
strBuf.append(column);
strBuf.append(" ");
}
// Add a return character at the end of the row.
strBuf.append("\r\n");
}
}
return strBuf.toString();
}
/* Write string data to a file.*/
private static void writeStringToFile(String data, String fileName)
{
try
{
// Get current executing class working directory.
String currentWorkingFolder = System.getProperty("user.dir");
// Get file path separator.
String filePathSeperator = System.getProperty("file.separator");
// Get the output file absolute path.
String filePath = currentWorkingFolder + filePathSeperator + fileName;
// Create File, FileWriter and BufferedWriter object.
File file = new File(filePath);
FileWriter fw = new FileWriter(file);
BufferedWriter buffWriter = new BufferedWriter(fw);
// Write string data to the output file, flush and close the buffered writer object.
buffWriter.write(data);
buffWriter.flush();
buffWriter.close();
System.out.println(filePath + " has been created.");
}catch(IOException ex)
{
System.err.println(ex.getMessage());
}
}
}
for more details visit https://www.dev2qa.com/convert-excel-to-json-in-java-example/
Related
I am accessing my Excel sheet data and I am able to get my output but along with that am getting an error:
Cannot invoke "org.apache.poi.ss.usermodel.Cell.getStringCellValue()" because the return value of org.apache.poi.ss.usermodel.Row.getCell(int) is null
I get this error on this line of code:
if(r.getCell(column).getStringCellValue().equalsIgnoreCase("Login ID")
This is my whole code:
package Exceltwo.guruExcel;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class excelDataProvider {
//Identify Testcases column by scanning the entire 1st row
//once column is identified then scan entire testcase column to identify purchase testcase row
//after you grab purchase testcase row = pull all the data of that row and feed into test
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("C:\\Users\\mimo\\Desktop\\workbookexample.xlsx");
XSSFWorkbook workbook=new XSSFWorkbook(fis);
int sheets = workbook.getNumberOfSheets();
for (int i = 0; i < sheets; i++)
{
if (workbook.getSheetName(i).equalsIgnoreCase("Sheet1"))
{
XSSFSheet sheet = workbook.getSheetAt(i);
//Identify Testcases column by scanning the entire 1st row
Iterator<Row> rows = sheet.iterator(); // sheet is collection of rows
Row firstrow = rows.next();
Iterator<Cell> ce = firstrow.cellIterator(); // row is collection of cells
int k = 0;
int column = 0;
while (ce.hasNext())
{
Cell value = ce.next();
if (value.getStringCellValue().equalsIgnoreCase("Testcase"))
{
column = k;
}
k++;
}
System.out.println(column);
// once column is identified then scan entire testcase column to identify purchase testcase row
while (rows.hasNext())
{
Row r = rows.next();
if (r.getCell(column).getStringCellValue().equalsIgnoreCase("Login ID"))
{
// after you grab purchase testcase row = pull all the data of that row and feed into test
Iterator<Cell> cv = r.cellIterator();
while (cv.hasNext())
{
Cell c = cv.next();
System.out.println(c);
}
}
}
}
}
// TODO Auto-generated method stub
}
Excel Screenshot
Console Screenshot
As pointed out in the comments r.getCell(column) can return null.
Another option (besides checking for null) is to use CellUtil.getCell(r, column) which will not return null, as it will create the cell if it doesn't exist.
See https://poi.apache.org/apidocs/dev/org/apache/poi/ss/util/CellUtil.html#getCell-org.apache.poi.ss.usermodel.Row-int-
**Add one more if block for checking whether the cell is null or not then it will execute without any error...**
while(rows.hasNext())
{
Row r=rows.next();
if(r.getCell(column)!=null)
{
if(r.getCell(column).getStringCellValue().equalsIgnoreCase("Login ID"))
{
Iterator<Cell> cv=r.cellIterator();
while(cv.hasNext())
{
Cell c = cv.next();
System.out.println(c);
}
}
}
}
Change this
while (cv.hasNext())
to this
while (cv.hasNext() == true)
It because, there is no available value after the next / down cells of the given cell.
I have an existing Excel workbook in which two "output" cells (with range name "rate" and "premium") have formulas based on values in other "input" cells (i.e. range names "loamamount", "loanterm", "age" and "smoker").
If, in the Excel workbook, I make all the input cells empty then the formulae evaluate to "#N/A". However when I populate the correct values in the input cells through poi and use the command
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
The value in the two cells is not recalculated and remains "#N/A".
Can anyone help me understand what I am doing wrong? The code is as follows:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFName;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class GetDataFromExcel {
public static void main(String[] args) throws IOException {
getData();
}
public static void getData() throws IOException {
String s, cCellName, cString;
XSSFName namedCell;
AreaReference aref;
CellReference[] crefs;
XSSFRow r;
XSSFCell c;
XSSFSheet sheet = null;
File directory = new File("./");
s = directory.getAbsolutePath();
s = s.substring(0, s.length() - 2);
InputStream ExcelFileToRead = new FileInputStream(s + "/src/main/java/Excel/Test1.xlsx");
XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
// Search for the Range names and set the input values
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("loanamount", 2000000);
map.put("age", 25);
map.put("smoker", "Y");
map.put("loanterm", 23);
for (HashMap.Entry<String, Object> entry : map.entrySet()) {
cCellName = entry.getKey();
namedCell = wb.getName(cCellName);
// Retrieve the cell at the named range and test its contents
aref = new AreaReference(namedCell.getRefersToFormula(), null);
crefs = aref.getAllReferencedCells();
for (int i = 0; i < crefs.length; i++) {
sheet = wb.getSheet(crefs[i].getSheetName());
r = sheet.getRow(crefs[i].getRow());
c = r.getCell(crefs[i].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
// extract the cell contents based on cell type etc.
cString = entry.getValue().toString(); // Add missing cell check
if (c.getCellType() == CellType.STRING) {
c.setCellValue(cString);
} else if (c.getCellType() == CellType.NUMERIC) {
c.setCellValue(Double.parseDouble(cString));
} else if (c.getCellType() == CellType.BOOLEAN) {
c.setCellValue(cString);
} else {
}
}
}
sheet = wb.getSheetAt(0);
XSSFFormulaEvaluator.evaluateAllFormulaCells(wb);
// wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
// Get all the output values requested
Iterator<String> i;
ArrayList<String> outputValues = new ArrayList<String>();
outputValues.add("rate");
outputValues.add("premium");
i = outputValues.iterator();
while (i.hasNext()) {
cCellName = i.next();
namedCell = wb.getName(cCellName);
// retrieve the cell at the named range and test its contents
aref = new AreaReference(namedCell.getRefersToFormula(), null);
crefs = aref.getAllReferencedCells();
for (int j = 0; j < crefs.length; j++) {
sheet = wb.getSheet(crefs[j].getSheetName());
r = sheet.getRow(crefs[j].getRow());
c = r.getCell(crefs[j].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);/////
// extract the cell contents based on cell type etc.
System.out.println(cCellName +" : "+c.getRawValue());
}
}
wb.close();
}
}
Your code part which should set values into cells does not set values into cells. So because there are no cell values set and the cells remain empty, the formulas will result in #N/A error.
This is because blank cells will not be of any cell type you are testing in your code. A blank cell is of CellType.BLANK and not CellType.STRING nor CellType.NUMERIC nor CellType.BOOLEAN. So none of your if... will be true and so no value will be set into the cells.
Rather than trying to set cell values dependent of cell types which cannot exist for blank cells, you should put cell values dependent on entry value type.
Example:
...
for (HashMap.Entry<String, Object> entry : map.entrySet()) {
cCellName = entry.getKey();
namedCell = wb.getName(cCellName);
// Retrieve the cell at the named range and test its contents
aref = new AreaReference(namedCell.getRefersToFormula(), null);
crefs = aref.getAllReferencedCells();
for (int i = 0; i < crefs.length; i++) {
sheet = wb.getSheet(crefs[i].getSheetName());
r = sheet.getRow(crefs[i].getRow());
c = r.getCell(crefs[i].getCol(), Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
// put cell values dependent on entry value type
Object o = entry.getValue();
if (o instanceof String) {
c.setCellValue((String)o);
} else if (o instanceof Number) {
c.setCellValue(((Number)o).doubleValue());
} else if (o instanceof Boolean) {
c.setCellValue((Boolean)o);
} else {
}
}
}
...
I have two programs in Java: one to create and write data to an XLSX file and the other to read data from the same file.
In my first program, I used the statements below to write data to the XLSX file.
FileOutputStream prelimOut = new FileOutputStream(new File("D:\\News\\Prelim.xlsx"));
XSSFWorkbook out = new XSSFWorkbook();
XSSFSheet spreadSheet = out.createSheet("ResultSheet");
and on my drive, I've the file created as expected.
When I'm trying to read the same file from a different program with this code
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class GetCellCount {
public static void main(String[] args) throws IOException {
FileInputStream input_document = new FileInputStream(new File("D:\\News\\Prelim.xlsx"));
XSSFWorkbook my_xlsx_workbook = new XSSFWorkbook(input_document);
XSSFSheet my_worksheet = my_xlsx_workbook.getSheetAt(0);
Iterator<Row> rowIterator = my_worksheet.iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC:
System.out.print(cell.getNumericCellValue() + "\t\t");
break;
case Cell.CELL_TYPE_STRING:
System.out.print(cell.getStringCellValue() + "\t\t");
break;
}
}
System.out.println("");
}
my_xlsx_workbook.close();
input_document.close();
}
}
it throws the below error
Exception in thread "main" org.apache.poi.POIXMLException: org.apache.poi.openxml4j.exceptions.InvalidFormatException: Package should contain a content type part [M1.13]
at org.apache.poi.util.PackageHelper.open(PackageHelper.java:39)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:258)
at GetCellCount.main(GetCellCount.java:14)
Caused by: org.apache.poi.openxml4j.exceptions.InvalidFormatException: Package should contain a content type part [M1.13]
at org.apache.poi.openxml4j.opc.ZipPackage.getPartsImpl(ZipPackage.java:203)
at org.apache.poi.openxml4j.opc.OPCPackage.getParts(OPCPackage.java:673)
at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:274)
at org.apache.poi.util.PackageHelper.open(PackageHelper.java:37)
... 2 more
When changing the path and accessing another XLSX file (created directly in Excel), the data appears correctly.
Also, when I checked the properties of both these Excel files by right-clicking on them, I see the "Type of File" as MS Office Excel OpenXML (.xlsx), which is the same for both files.
The following code demonstrates creating a new XLSX file with data, writing it to disk, and reading the data back from the file.
The example uses a simple Person class containing a String, a LocalDate, and an Int to produce test data.
This is the created XLSX file viewed with LibreOffice after we've written that test data to it:
After writing the file, we read its contents back in and create Person objects:
Could not parse row 0 to person
Person from file: Khaled, born 1988-03-26, pets: 1
Person from file: Hans, born 1998-09-20, pets: 2
Person from file: Alena, born 1977-01-12, pets: 0
The warning in the first line occurs since we can't convert the header row
Name Date of Birth Nr of Pets
to a Person object.
Here's the code taken from the repository containing the complete project:
/**
* Writes person data to an XLSX file and reads it back from the file.
*/
public class ReadWriteTests {
public static void main(String... args) {
var people = List.of(
new Person("Khaled", LocalDate.of(1988, 3, 26), 1),
new Person("Hans", LocalDate.of(1998, 9, 20), 2),
new Person("Alena", LocalDate.of(1977, 1, 12), 0)
);
String xlsxFileName = System.getenv("HOME") + "/people.xlsx";
writeToXlsxFile(people, xlsxFileName);
List<Person> peopleFromFile = readFromXlsxFile(xlsxFileName);
peopleFromFile.forEach(person ->
System.out.println("Person from file: " + person));
}
private static List<Person> readFromXlsxFile(String xlsxFileName) {
return getRows(new File(xlsxFileName)).stream()
.map(row -> rowToPerson(row))
// Remove empty Optionals
.flatMap(Optional::stream)
.collect(Collectors.toList());
}
private static Optional<Person> rowToPerson(Row row) {
Optional<Person> personMaybe;
try {
String name = row.getCell(0).getStringCellValue();
Date date = row.getCell(1).getDateCellValue();
// Convert from Date to LocalDate
LocalDate dateOfBirth = LocalDate.ofInstant(
date.toInstant(), ZoneId.systemDefault());
int nrOfPets = (int) row.getCell(2).getNumericCellValue();
personMaybe = Optional.of(new Person(name, dateOfBirth, nrOfPets));
} catch (IllegalStateException ex) {
System.err.println("Could not parse row " + row.getRowNum()
+ " to person");
personMaybe = Optional.empty();
}
return personMaybe;
}
private static List<Row> getRows(File xlsx) {
var rows = new ArrayList<Row>();
try (var workbook = new XSSFWorkbook(xlsx)) {
// Get each row from each sheet
workbook.forEach(sheet -> sheet.forEach(rows::add));
// If Apache POI tries to open a non-existent file it will throw
// an InvalidOperationException, if it's an unrecognized format
// it will throw a NotOfficeXmlFileException.
// We catch them all to be safe.
} catch (Exception e) {
System.err.println("Could not get rows from "
+ xlsx.getAbsolutePath());
e.printStackTrace();
}
return rows;
}
private static void writeToXlsxFile(List<Person> people, String fileName) {
try (var fileStream = new FileOutputStream(fileName);
var workbook = new XSSFWorkbook()
) {
var sheet = workbook.createSheet("Test People Sheet");
// Create a header row describing what the columns mean
CellStyle boldStyle = workbook.createCellStyle();
var font = workbook.createFont();
font.setBold(true);
boldStyle.setFont(font);
var headerRow = sheet.createRow(0);
addStringCells(headerRow,
List.of("Name", "Date of Birth", "Nr of Pets"),
boldStyle);
// Define how a cell containing a date is displayed
CellStyle dateCellStyle = workbook.createCellStyle();
dateCellStyle.setDataFormat(workbook.getCreationHelper()
.createDataFormat()
.getFormat("yyyy/m/d"));
// Add the person data as rows
for (int i = 0; i < people.size(); i++) {
// Add one due to the header row
var row = sheet.createRow(i + 1);
var person = people.get(i);
addCells(person, row, dateCellStyle);
}
workbook.write(fileStream);
} catch (IOException e) {
System.err.println("Could not create XLSX file at " + fileName);
e.printStackTrace();
}
}
private static void addCells(Person person, Row row,
CellStyle dateCellStyle) {
var classCell = row.createCell(0, CellType.STRING);
classCell.setCellValue(person.getName());
var dateOfBirthCell = row.createCell(1, CellType.NUMERIC);
// Convert LocalDate to a legacy Date object
Date dateOfBirth = Date.from(person.getDateOfBirth()
.atStartOfDay(ZoneId.systemDefault()).toInstant());
dateOfBirthCell.setCellValue(dateOfBirth);
dateOfBirthCell.setCellStyle(dateCellStyle);
var petCell = row.createCell(2, CellType.NUMERIC);
petCell.setCellValue(person.getNrOfPets());
}
// Adds strings as styled cells to a row
private static void addStringCells(Row row, List<String> strings,
CellStyle style) {
for (int i = 0; i < strings.size(); i++) {
var cell = row.createCell(i, CellType.STRING);
cell.setCellValue(strings.get(i));
cell.setCellStyle(style);
}
}
static class Person {
private final String name;
private final LocalDate dateOfBirth;
private final int nrOfPets;
Person(String name, LocalDate dateOfBirth, int nrOfPets) {
this.name = name;
this.dateOfBirth = dateOfBirth;
this.nrOfPets = nrOfPets;
}
String getName() {
return name;
}
LocalDate getDateOfBirth() {
return dateOfBirth;
}
int getNrOfPets() {
return nrOfPets;
}
#Override
public String toString() {
return name + ", born " + dateOfBirth + ", pets: " + nrOfPets;
}
}
}
Here's more on creating spreadsheets with Apache POI.
I'm a newbie to java & I'm trying to read numeric data from a text file & I want to write each number in a separate cell in an Excel spreadsheet.
Input data is as below:(abc.txt)
3008,45,14,277,10,6371,223,208,116,3036,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,2 2893,114,16,108,30,5066,245,223,102,4340,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,2
I want each value in a different cell. I'm using Apache POI for using excel sheets. This is what I'm able to code till now
package com.example.practise;
import java.io.*;
import java.util.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
//import org.apache.poi.ss.usermodel.Creationhelper;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
public class MultivariateDT {
public static void main(String[] args) throws IOException{
BufferedReader bufferedReader = new BufferedReader(new FileReader("C:/Users/419803/Desktop/abc.txt"));
FileOutputStream out = new FileOutputStream("C:/Users/419803/Desktop/workbook.xls");
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet1 = wb.createSheet("new sheet");
Row row = null;
Cell cell = null;
String line = null;
String delimiter = ",";
while ((line = bufferedReader.readLine()) != null)
{
String[] temp=null;
String str = " ";
temp = line.split(delimiter);
for(int i =0; i < temp.length ; i++)
{
str = temp[i] + str;
int rownum;
for (rownum =0; rownum < 100; rownum++)
{
row = sheet1.createRow(rownum);
for (int cellnum =0; cellnum <temp.length; cellnum ++)
{
cell = row.createCell(cellnum);
cell.setCellValue(temp[i]);
}
}
}
System.out.println();
}
wb.write(out);
out.close();
}
}
No.of rows & cells that have to be created are correct, but data in excel file is wrong.
In excel file only showing 2,2,2,2 so on.
Can any one please help me??
I think you have too many for-loops with which you are iterating too much, i.e. first you loop over all items in the line, for these you create 100 rows and in each row you iterate overa all items in the line again, creating rows, bug in setCellValue() you are using temp[i], not temp[cellnum], so you are first creating 100 rows with temp[0], then 100 rows with all temp[1], ...
It depends on how the resulting spreadsheet should look like, but I would try to adjust the for-loops accordingly, e.g. for one row per line you would remove the outer too for-loops, for 100 rows per line you would remove the single outer for-loop.
I am reading an Excel sheet using POI's XSSF and SAX (Event API). The Excel sheet has thousands of rows of user information like user name, email, address, age, department etc.
I need to read each row from Excel, convert it into a User object and add this User object to a List of User objects.
I can read the Excel sheet successfully, but I am not sure at what point while reading I should create an instance of the User object and populate it with the data from the Excel sheet.
Below is my entire working code.
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
public class ExcelSheetParser {
enum xssfDataType {
BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER,
}
int countrows = 0;
class XSSFSheetHandler extends DefaultHandler {
/**
* Table with styles
*/
private StylesTable stylesTable;
/**
* Table with unique strings
*/
private ReadOnlySharedStringsTable sharedStringsTable;
/**
* Destination for data
*/
private final PrintStream output;
private List<?> list = new ArrayList();
private Class clazz;
/**
* Number of columns to read starting with leftmost
*/
private final int minColumnCount;
// Set when V start element is seen
private boolean vIsOpen;
// Set when cell start element is seen;
// used when cell close element is seen.
private xssfDataType nextDataType;
// Used to format numeric cell values.
private short formatIndex;
private String formatString;
private final DataFormatter formatter;
private int thisColumn = -1;
// The last column printed to the output stream
private int lastColumnNumber = -1;
// Gathers characters as they are seen.
private StringBuffer value;
/**
* Accepts objects needed while parsing.
*
* #param styles
* Table of styles
* #param strings
* Table of shared strings
* #param cols
* Minimum number of columns to show
* #param target
* Sink for output
*/
public XSSFSheetHandler(StylesTable styles,
ReadOnlySharedStringsTable strings, int cols, PrintStream target, Class clazz) {
this.stylesTable = styles;
this.sharedStringsTable = strings;
this.minColumnCount = cols;
this.output = target;
this.value = new StringBuffer();
this.nextDataType = xssfDataType.NUMBER;
this.formatter = new DataFormatter();
this.clazz = clazz;
}
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
if ("inlineStr".equals(name) || "v".equals(name)) {
vIsOpen = true;
// Clear contents cache
value.setLength(0);
}
// c => cell
else if ("c".equals(name)) {
// Get the cell reference
String r = attributes.getValue("r");
int firstDigit = -1;
for (int c = 0; c < r.length(); ++c) {
if (Character.isDigit(r.charAt(c))) {
firstDigit = c;
break;
}
}
thisColumn = nameToColumn(r.substring(0, firstDigit));
// Set up defaults.
this.nextDataType = xssfDataType.NUMBER;
this.formatIndex = -1;
this.formatString = null;
String cellType = attributes.getValue("t");
String cellStyleStr = attributes.getValue("s");
if ("b".equals(cellType))
nextDataType = xssfDataType.BOOL;
else if ("e".equals(cellType))
nextDataType = xssfDataType.ERROR;
else if ("inlineStr".equals(cellType))
nextDataType = xssfDataType.INLINESTR;
else if ("s".equals(cellType))
nextDataType = xssfDataType.SSTINDEX;
else if ("str".equals(cellType))
nextDataType = xssfDataType.FORMULA;
else if (cellStyleStr != null) {
// It's a number, but almost certainly one
// with a special style or format
int styleIndex = Integer.parseInt(cellStyleStr);
XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
this.formatIndex = style.getDataFormat();
this.formatString = style.getDataFormatString();
if (this.formatString == null)
this.formatString = BuiltinFormats
.getBuiltinFormat(this.formatIndex);
}
}
}
public void endElement(String uri, String localName, String name)
throws SAXException {
String thisStr = null;
// v => contents of a cell
if ("v".equals(name)) {
// Process the value contents as required.
// Do now, as characters() may be called more than once
switch (nextDataType) {
case BOOL:
char first = value.charAt(0);
thisStr = first == '0' ? "FALSE" : "TRUE";
break;
case ERROR:
thisStr = "\"ERROR:" + value.toString() + '"';
break;
case FORMULA:
// A formula could result in a string value,
// so always add double-quote characters.
thisStr = '"' + value.toString() + '"';
break;
case INLINESTR:
// TODO: have seen an example of this, so it's untested.
XSSFRichTextString rtsi = new XSSFRichTextString(value
.toString());
thisStr = '"' + rtsi.toString() + '"';
break;
case SSTINDEX:
String sstIndex = value.toString();
try {
int idx = Integer.parseInt(sstIndex);
XSSFRichTextString rtss = new XSSFRichTextString(
sharedStringsTable.getEntryAt(idx));
thisStr = '"' + rtss.toString() + '"';
} catch (NumberFormatException ex) {
output.println("Failed to parse SST index '" + sstIndex
+ "': " + ex.toString());
}
break;
case NUMBER:
String n = value.toString();
if (this.formatString != null)
thisStr = formatter.formatRawCellContents(Double
.parseDouble(n), this.formatIndex,
this.formatString);
else
thisStr = n;
break;
default:
thisStr = "(TODO: Unexpected type: " + nextDataType + ")";
break;
}
// Output after we've seen the string contents
// Emit commas for any fields that were missing on this row
if (lastColumnNumber == -1) {
lastColumnNumber = 0;
}
for (int i = lastColumnNumber; i < thisColumn; ++i)
output.print(',');
// Might be the empty string.
output.print(thisColumn +" : "+thisStr);
// Update column
if (thisColumn > -1)
lastColumnNumber = thisColumn;
} else if ("row".equals(name)) {
// Print out any missing commas if needed
if (minColumns > 0) {
// Columns are 0 based
if (lastColumnNumber == -1) {
lastColumnNumber = 0;
}
for (int i = lastColumnNumber; i < (this.minColumnCount); i++) {
output.print(',');
}
}
// We're onto a new row
output.println();
output.println(countrows++);
lastColumnNumber = -1;
}
}
/**
* Captures characters only if a suitable element is open. Originally
* was just "v"; extended for inlineStr also.
*/
public void characters(char[] ch, int start, int length)
throws SAXException {
if (vIsOpen)
value.append(ch, start, length);
}
/**
* Converts an Excel column name like "C" to a zero-based index.
*
* #param name
* #return Index corresponding to the specified name
*/
private int nameToColumn(String name) {
int column = -1;
for (int i = 0; i < name.length(); ++i) {
int c = name.charAt(i);
column = (column + 1) * 26 + c - 'A';
}
return column;
}
}
// /////////////////////////////////////
private OPCPackage xlsxPackage;
private int minColumns;
private PrintStream output;
private Class clazz;
/**
* Creates a new XLSX -> CSV converter
*
* #param pkg
* The XLSX package to process
* #param output
* The PrintStream to output the CSV to
* #param minColumns
* The minimum number of columns to output, or -1 for no minimum
*/
public ExcelSheetParser(OPCPackage pkg, PrintStream output, int minColumns, Class clazz) {
this.xlsxPackage = pkg;
this.output = output;
this.minColumns = minColumns;
this.clazz = clazz;
}
/**
* Parses and shows the content of one sheet using the specified styles and
* shared-strings tables.
*
* #param styles
* #param strings
* #param sheetInputStream
*/
public void processSheet(StylesTable styles,
ReadOnlySharedStringsTable strings, InputStream sheetInputStream)
throws IOException, ParserConfigurationException, SAXException {
InputSource sheetSource = new InputSource(sheetInputStream);
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxFactory.newSAXParser();
XMLReader sheetParser = saxParser.getXMLReader();
ContentHandler handler = new XSSFSheetHandler(styles, strings,
this.minColumns, this.output, this.clazz);
sheetParser.setContentHandler(handler);
sheetParser.parse(sheetSource);
}
/**
* Initiates the processing of the XLS workbook file to CSV.
*
* #throws IOException
* #throws OpenXML4JException
* #throws ParserConfigurationException
* #throws SAXException
*/
public void process() throws IOException, OpenXML4JException,
ParserConfigurationException, SAXException {
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(
this.xlsxPackage);
XSSFReader xssfReader = new XSSFReader(this.xlsxPackage);
StylesTable styles = xssfReader.getStylesTable();
XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) xssfReader
.getSheetsData();
int index = 0;
while (iter.hasNext()) {
InputStream stream = iter.next();
String sheetName = iter.getSheetName();
this.output.println(sheetName + " [index=" + index + "]:");
processSheet(styles, strings, stream);
stream.close();
++index;
}
}
}
What I'd probably do is start building the User object when the row starts. As you hit the cells in the row, you populate your User object. When the row ends, validate the User object, and if it's fine add it then. Because you're doing SAX parsing, you'll get the start and events for all of these, so you can attach your logic there.
I'd suggest you take a look at XLSX2CSV in the Apache POI Examples. It shows how to go about handling the different kinds of cell contents (which you'll need for populating your user object), how to do something when you reach the end of the row, as well as handling missing cells etc.
I think you can create a user object at following location in your code:
// We're onto a new row
output.println();
// Convert output to a new user object
// ....
// ....
First of all where you are saving value in thisStr variable, if this is a valid value then put this value in Map.
You should create USer object in endElement() method in
else if ("row".equals(name)) {
// use map create USER object here
}
and You can add Users object in global list and if you want to persist it then you can persist it sheet by sheet OR all data at a time.
while (iter.hasNext()) {
InputStream stream = iter.next();
String sheetName = iter.getSheetName();
this.output.println(sheetName + " [index=" + index + "]:");
processSheet(styles, strings, stream);
stream.close();
++index;
//for persisting USERS data sheet by sheet write your code here.........
}
// for persisting complete data of all sheets write your code here...
This is working for me.