I am trying to make use of Apache POI to read an excel file and convert it to a 2-dimensional object array. Attached is the code section.
Workbook workbook = new XSSFWorkbook(inputStream);
Sheet firstSheet = workbook.getSheetAt(1);
int numRows = 3;
int cols = 5;
double[][] excelData = new double[numRows][cols];
for (int i = 1; i < numRows; i++) {
Row row = firstSheet.getRow(i);
if (row != null) {
for (int j = 1; j < cols; j++) {
Cell cell = row.getCell(j);
if (cell != null) {
try {
excelData[i][j] = cell.getNumericCellValue();
} catch (IllegalStateException e) {
System.out.println("Cell data is not a double");
}
}
}
}
}
workbook.close();
inputStream.close();
return excelData;
}
enter image description here This is my excel sheet and I want to "just" read the blue part of it as a 2d array, but after running the code the first row and column all are zero and I don't want it, appreciate your help on how can quickly pull out all the zeros enter image description here.
You need to change index in the 1st loop to 0 (first field in excel file)
but in row you must provide index + 1 bc you need to read from the 2nd field.
Same analogy for 2nd loop and cell field
Workbook workbook = new XSSFWorkbook(new File("d:\\book1.xlsx"));
Sheet firstSheet = workbook.getSheetAt(1);
int numRows = 3;
int cols = 5;
double[][] excelData = new double[numRows][cols];
for (int i = 0; i < numRows; i++) {
Row row = firstSheet.getRow(i + 1);
if (row != null) {
for (int j = 0; j < cols; j++) {
Cell cell = row.getCell(j + 1);
if (cell != null) {
try {
if (cell.getCellType().equals(CellType.NUMERIC)) {
excelData[i][j] = Double.valueOf(cell.getNumericCellValue());
}
} catch (IllegalStateException e) {
System.out.println("Cell data is not a double");
}
}
}
}
}
workbook.close();
Returned result for it:
0.041256 0.033079 -0.01138 -0.02138 -0.01138
0.041256 0.033079 -0.01138 -0.01138 -0.01138
0.020628 0.01654 -0.00569 -0.10569 -0.00569
I have a string arraylist name as code like this:
[a,b,c,d]
and another string arraylist that contain data like this name as DWS:
[a11,a22,a33,a44,a55,a66,a77,b11,b22,b33,b44,b55,b66,b77,c11,c22,c33,c44,c55,c66,c77,d11,d22,d33,d44,d55,d66,d77]
What I want to do is I want to write to the DWS arraylist into excel file like this:
I have tried this way:
FileInputStream file1 = new FileInputStream(new File(namefile));
XSSFWorkbook wb1 = new XSSFWorkbook(file1);
XSSFSheet sheet1 = wb1.getSheetAt(0);
int limit = 7;
for (int m = 0; m < code.size(); m++) {
for (int x = 0; x < DWS.size(); x++) {
for (int i = 0; i < limit; i++) {
Row row2 = sheet1.getRow(i + 2);
Cell cell = row2.createCell(m * 3 + 4);
cell.setCellValue(DWS.get(x));
}
}
}
but the result that I get is:
Any idea how to overcome this problem?
UPDATE
I change my code like this as suggested:
int limit = 7;
for (int i = 0; i < limit; i++) {
Row row2 = sheet1.getRow(i + 2);
for (int m = 0; m < code.size(); m++) {
Cell cell = row2.createCell(m * 3 + 4);
cell.setCellValue(DWS.get(i));
}
}
and the result is like this:
It only loop the first 7 data. I need it to continue for the rest of the arraylist. like the first image.
UPDATE
let me explain again the flow of my code
1) It will loop the DWS arraylist into the first cell which is cell no 5 and loop until the last row which row no 7,
2) then , after it reach row no 7, it then supposedly create a new cell which in line Cell cell = row2.createCell(m * 3 + 4);and then again, continue looping from the DWS arraylist data.
3) this steps will continue until it reach the last arraylist data of DWS
is that possible to do that?
UPDATE 2.0
I change to this:
int cellValueIndex = 0;
for (int i = 0; i < limit; i++) {
Row row2 = sheet1.getRow(i + 2);
for (int m = 0; m < code.size(); m++) {
Cell cell = row2.createCell(m * 3 + 4);
cell.setCellValue(DWS.get(cellValueIndex));
cellValueIndex++;
}
}
but I got error like this:
java.lang.IndexOutOfBoundsException
UPDATE 3.0
I change to this but the result is still wrong
int cellValueIndex = 0;
for (int i = 0; i < limit; i++) {
Row row2 = sheet1.getRow(i + 2);
for (int m = 0; m < code.size(); m++) {
Cell cell = row2.createCell(m * 3 + 4);
cell.setCellValue(DWS.get(cellValueIndex));
}
cellValueIndex = cellValueIndex + 1;
}
UPDATE 4.0
I have change to this:
int cellValueIndex = 0;
int counter = 0;
for (int i = 0; i < limit; i++) {
Row row2 = sheet1.getRow(i + 2);
Cell cell = row2.createCell(4);
cell.setCellValue(DWS.get(cellValueIndex));
cellValueIndex++;
int x = row2.getRowNum();
if (x == limit) {
for (int m = 1; m < code.size(); m++) {
Cell cell1 = row2.createCell(m * 3 + 4);
cell1.setCellValue(DWS.get(cellValueIndex + 1));
cellValueIndex++;
}
}
}
The result is like this:
But when I try to set the i=0;, like this:
int cellValueIndex = 0;
for (int i = 0; i < total1; i++) {
Row row2 = sheet1.getRow(i + 2);
Cell cell = row2.createCell(4);
cell.setCellValue(DWS.get(cellValueIndex));
cellValueIndex++;
int x = row2.getRowNum();
if (x == total1) {
i = 0;
for (int m = 1; m < shiftcode.size(); m++) {
Cell cell1 = row2.createCell(m * 3 + 4);
cell1.setCellValue(DWS.get(cellValueIndex));
cellValueIndex++;
i++;
}
}
}
I got error like this:
java.lang.IndexOutOfBoundsException
There are 3 for loops going on here! However as I see, you are creating cells in the third loop, where the value of the x is the last representational value from the DWS. If DWS is just a source of the cell values then you should have a separate index for that rather than keeping a loop for that.
In this case, though you don't realize from the end result, it is creating DWS.size times tables and it's cells! You don't realize it from the result because what you see is the last executed table which contains the value d77 only. And you are putting ONLY one value to all the cells because in the last loop DWS.get(x) is always constant, you don't have to do that.
You have to put different values to each and every cell.
Solution:
You need just 2 loops.
int cellValueIndex = 0;
for (int m = 0; m < limit; m++) {
// create a row here
for (int n = 0; n < code.length; n++) {
// take the value from DWS like DWS.get(cellValueIndex) and
// keep incrementing cellValueIndex by one always
}
}
If you use apache csv printer you can print rows easily. I wrote a solution for you that work:
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
public class DataGenerator {
private static final String[] HEADERS = {"a", "b", "c", "d"};
private static final String[] DATA = {"a11", "a22", "a33", "a44", "a55", "a66", "a77", "b11", "b22", "b33", "b44", "b55", "b66", "b77", "c11", "c22", "c33", "c44", "c55", "c66", "c77", "d11", "d22", "d33", "d44", "d55", "d66", "d77"};
private static CSVPrinter csvPrinter;
private static final CSVFormat getFileCsvFormat = CSVFormat.newFormat(';')
.withHeader(HEADERS)
.withRecordSeparator('\n');
private static final int rowSize = DATA.length / HEADERS.length; // 7
#BeforeAll
private static void setupCsv() throws IOException {
final long date = new Date().getTime();
final String fileTestData = "src/test/resources/csv/testdata.csv";
final FileWriter getDataWriter = new FileWriter(fileTestData);
csvPrinter = new CSVPrinter(getDataWriter, getFileCsvFormat);
System.out.println("Files created:" + fileTestData);
}
#Test
void printCsv() throws IOException {
final int dataLength = DATA.length;
final List<String[]> columns = getColumns(DATA);
final String[][] rows = transformToRows(columns);
for (int i = 0; i < rows.length; i++) {
printRow(rows[i]);
}
csvPrinter.flush();
}
private void printRow(final String[] row) {
try {
csvPrinter.printRecord(row);
} catch (final IOException e) {
e.printStackTrace();
}
}
private List<String[]> getColumns(final String[] data) {
final List<String[]> partitions = new ArrayList<>();
final int dataLength = data.length;
for (int i = 0; i < dataLength; i += rowSize) {
partitions.add(Arrays.copyOfRange(DATA, i, Math.min(i + rowSize, dataLength)));
}
return partitions;
}
/**
* a1 a2
* b1 b2
* - transform to: -
* a1 b1
* a2 b2
*/
private String[][] transformToRows(final List<String[]> columns) {
final String[][] dataMatrix = new String[rowSize][HEADERS.length];
for (int i = 0; i < columns.size(); i++) {
for (int j = 0; j < rowSize; j++) {
//{{a1, a2}, {b1, b2}}
dataMatrix[j][i] = columns.get(i)[j];
}
}
return dataMatrix;
}
I think your main problem however was how to transform your data from a column structure to a row structure, which you can print left to right. The input data is split into columns easily, but most csv/excel/... printers work by row. You can use the transformToRows method from my example to do this.
I'm using Apache POI to read and write to excel files. However, while trying to write to two different sheets in 1 workbook, my second for loop is not executing. Therefore, only the first worksheet is written to while the second worksheet is not.
for (int r = 4; r < outTotalRows1; r++) {
row2 = outSheet1.getRow(r);
if (row2.getCell(3) == null) {
for (int t = 3; t <= 47; t++) {
outCell = row2.createCell(t);
outCell.setCellValue(BSMeanArray[t - 3]);
FileOutputStream outWrite = new FileOutputStream(new File(outputFileName));
outWorkbook.write(outWrite);
outWrite.close();
}
}
if (row2.getCell(50) == null) { // if the velocity cell is == null, then set cell value to array established and then break
for (int u = 50; u < 94; u++) {
outCell = row2.createCell(u); // maybe this line wrong?
outCell.setCellValue(BFMeanArray[u - 50]);
FileOutputStream outWrite = new FileOutputStream(new File(outputFileName));
outWorkbook.write(outWrite);
outWrite.close();
}
}
}
// THIS LOOP NOT EXECUTING
for(int r = 4; r < outTotalRows2; r++){
System.out.println("executed");
row3 = outSheet2.getRow(r);
if (row3.getCell(3) == null) {
for (int u = 3; u <= 47; u++) {
outCell = row3.createCell(u);
outCell.setCellValue(FFSMeanArray[u - 3]);
FileOutputStream outWrite = new FileOutputStream(new File(outputFileName));
outWorkbook.write(outWrite);
outWrite.close();
}
}
if (row3.getCell(50) == null) {
for (int u = 50; u <= 94; u++) {
outCell = row3.createCell(u);
outCell.setCellValue(FFFMeanArray[u - 50]);
FileOutputStream outWrite = new FileOutputStream(new File(outputFileName));
outWorkbook.write(outWrite);
outWrite.close();
}
}
}
I'm writing a code where I have to compare data between excel rows, if I find a match I want to increment my finalIndex by 1 and once the matches are found I need to merge the cells. Here I'm unable to understand how to maintain the track of the starting row number.
Below is my code. How can I do this?
HSSFWorkbook workbook = new HSSFWorkbook(fin);
HSSFSheet sheet = workbook.getSheetAt(0);
int row = sheet.getPhysicalNumberOfRows();
String currentLawName, currentCountry, currentAssociate, previousLawName, previousCountry, previousAssociate;
String currentPages, previousPages;
int startIndex = 0, finalIndex = 0, tempNum = 0;
System.out.println(row);
for (int i = 2; i < row; i++) {
currentAssociate = sheet.getRow(i).getCell(1).toString();
currentLawName = sheet.getRow(i).getCell(3).toString();
currentCountry = sheet.getRow(i).getCell(4).toString();
currentPages = sheet.getRow(i).getCell(5).toString();
previousAssociate = sheet.getRow(i - 1).getCell(1).toString();
previousLawName = sheet.getRow(i - 1).getCell(3).toString();
previousCountry = sheet.getRow(i - 1).getCell(4).toString();
previousPages = sheet.getRow(i - 1).getCell(5).toString();
if (currentAssociate.equals(previousAssociate) && currentCountry.equals(previousCountry)
&& currentLawName.equals(previousLawName) && currentPages.equals(previousPages)) {
finalIndex += 1;
} else {
finalIndex = 0;
}
}
System.out.println(finalIndex + "\t" + tempNum);
I am new to Apache-poi and using 3.8 version of poi. While writing value in the Excel,i check for the column names if they matched, i will write some value in that column and finish it, and again i will start writing on header. The problem is if write three column values only last column values are add or saved and first two values are not saved in the column. Can anyone tell what went wrong.
(sorry, in case any mistake)
Code:
int i = 0;
Row row = sheet.createRow(i);
CellStyle cellStyle = workbook.createCellStyle();
cellStyle.setFillBackgroundColor(HSSFColor.LIGHT_ORANGE.index);
String validate_header = null;
while (iterator.hasNext()) {
if (eiterator.hasNext()) {
validate_header = eiterator.next();
}
Cell cell = row.createCell(i);
String col_heading = iterator.next();
cell.setCellValue(col_heading);
if(col_heading.equalsIgnoreCase("Assigned Date"))
{
Add_value(i, col_heading, row, sheet);
row=sheet.getRow(0);
cell=row.getCell(i);
}
else if(col_heading.startsWith("Review"))
{
int count=-1;
int n=Col_values.get("Defect Summary").size();
for (int j = 0; j < n; j++) {
row = sheet.createRow(count);
cell = row.createCell(i);
String s="External QC Defect ";
cell.setCellValue(s);
count++;
}
row=sheet.getRow(0);
cell=row.getCell(i);
}
sheet.autoSizeColumn(i);
i++;
}
private static Sheet Add_value(int k,String name,Row row, Sheet sheet) {
System.out.println("Inside the add method");
if(name.equalsIgnoreCase("Assigned Date")||name.equalsIgnoreCase("Reported Date") )
{
vector = Col_values.get("TargetDate");
int count = 1;
System.out.println("IF Size of the vector " + vector.size());
for (int j = 0; j < vector.size(); j++) {
row = sheet.createRow(count);
cell = row.createCell(k);
String s = (String) vector.get(j);
System.out.println(s);
cell.setCellValue(s);
count++;
}
}
else
{
vector = Col_values.get("Defect Summary");
int count = 1;
System.out.println("ELSE Size of the vector " + vector.size());
for (int j = 0; j < vector.size(); j++) {
row = sheet.createRow(count);
cell = row.createCell(k);
String s = (String) vector.get(j);
System.out.println(s);
cell.setCellValue(s);
count++;
}
}
return sheet;
}
'
Can u tell what went Wrong?
It seems that Add_value starts creating rows from top. Therefore on the second call the old rows are removed.
Replace
row = sheet.createRow(count);
with
row = k == 0 ? sheet.createRow(count) : sheet.getRow(count);