printing data columnwise in same workbook - java poi - java

I am using Java and POI to print some data to excel files. I think I am just missing a small logic to solve this question. I have data stored in array lists in following format:
a = [1,2,3] // arraylist
b = [4,5,6] // arraylist
c = [7,8,9] // arraylist
I want to print this data columnwise to excel file in below given format:
1 | 4 | 7
2 | 5 | 8
3 | 6 | 9
The code that I am using is as below:
public final_out = new FileOutputStream(new File(final_output_path));
public XSSFWorkbook workbook = new XSSFWorkbook();
public XSSFSheet sheet = workbook.createSheet("data_vertical_final");
public Row row;
for (int i=0; i < a.size(); i++) {
String value = a.get(i);
row = sheet.createRow(i);
Cell cell = row.createCell(13);
cell.setCellValue(value);
}
for (int i=0; i < b.size(); i++) {
String value = b.get(i);
row = sheet.createRow(i);
Cell cell = row.createCell(15);
cell.setCellValue(value);
}
for (int i=0; i < c.size(); i++) {
String value = a.get(i);
row = sheet.createRow(i);
Cell cell = row.createCell(17);
cell.setCellValue(value);
}
workbook.write(final_out);
workbook.close();
final_out.close();
Error I am getting:
There is no error, but everything is getting overwritten in new excel file and the final output looks broken. Do I need to make new workbooks for every loop? or there is something I am missing.
P.S:
The data that is shown below is just an example. Some of my original files that I am using are between 1000 to 2000 values or maybe more.
I want to dynamically create the rows and extract the values from arraylists and store it in rows that I created.

Create only a.size() rows,
not a.size() squared rows.
Don't overwrite them in your code.
I assume that a.size() == b.size() and b.size() == c.size().
public List<Row> rows = new ArrayList<Row>(a.size());
for (int i=0; i < a.size(); i++) {
rows.add(sheet.createRow(i));
}
for (int i=0; i < a.size(); i++) {
String value = a.get(i);
Cell cell = rows.get(i).createCell(13);
cell.setCellValue(value);
}
for (int i=0; i < b.size(); i++) {
String value = b.get(i);
Cell cell = rows.get(i).createCell(15);
cell.setCellValue(value);
}
for (int i=0; i < c.size(); i++) {
String value = a.get(i);
Cell cell = rows.get(i).createCell(17);
cell.setCellValue(value);
}
If you already solve the problem:
It would be even cleaner to place a, b and c into one collection and use only one loop to iterate through them (in place of 3 separate loops).
I assume that a is the longest list.
Check this out:
public List<Row> rows = new ArrayList<>(a.size());
for (int i=0; i < a.size(); i++) {
rows.add(sheet.createRow(i));
}
List<List<String>> alphabet = new ArrayList<>();
alphabet.add(a);
alphabet.add(b);
alphabet.add(c);
for(int i=0; i < alphabet.size(); i++) {
for (int j=0; j < alphabet.get(i).size(); j++) {
String value = alphabet.get(i).get(j);
Cell cell = rows.get(j).createCell(13 + i*2); //<- 13, 15, 17...
cell.setCellValue(value);
}
}

Related

How to continue to loop and create new cell based on arraylist

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.

Read excel and Assign cell Value by column to an array

Using apache.poi, I am trying to read an Excel sheet and using the below code, I am printing all the values inside Excel..
for (int i = 0; i < rowCount + 1; i++) {
Row row = searcsheet.getRow(i);
// Create a loop to print cell values in a row
for (int j = 0; j < row.getLastCellNum(); j++) {
// Print Excel data in console
String location = (row.getCell(j).getStringCellValue()+ "");
System.out.println(location);
}
When I print the location System.out.println(location);, it prints my all Excel sheet data. I haven't any control over there. I am trying divide the value by the column.
Suppose I have 3 cells and I want to get a value like firstname[],lastname[],age[] so that I can do any operation by the indexing. I am not getting any solution.
Here is my full code
https://codeshare.io/anNwy3
Create a 2D String array. When iterating store the contents into the array
String[][] excelData = new String[numColumns][searcsheet.getLastRowNum()];
//numColumns is the number of columns in the excel sheet.
for (int i = 0; i < rowCount + 1; i++) {
Row row = searcsheet.getRow(i);
for (int j = 0; j < row.getLastCellNum(); j++) {
String data = (row.getCell(j).getStringCellValue()+ "");
excelData[j][i] = data;
}
}
This transpose data when storing it into the array (note: excelData[j][i] and not excelData[i][j]).
With this, you can get all the contents of the first column as excelData[0].

Displaying the string values of 2 dimensional Object array

I am trying to display the contents of an array after iterating through rows and columns of a JTable. I tried Arrays.toString(myTwoDimensionalArrayVariable) but it won't display the string values.
My goal is to check duplicates for every column per row of a destination JTable when user tries to add row values from a source JTable that's why I want to display the contents of the array.
The values on columns are combination of double, String, and int.
int myRowCount = aJTableParameter.getRowCount();
int myColumnCount = aJTableParameter.getColumnCount();
Object[][] myRowValues = new Object[myRowCount][myColumnCount];
for (int j = 0; j < myRowCount; j++) {
for(int i = 0; i< myColumnCount; i++){
myRowValues[j][i] = aDestinationTable.getValueAt(j, i);
}
}
System.out.println(Arrays.toString(myRowValues));
if (Arrays.asList(myRowValues).contains(column1Value)
&& Arrays.asList(myRowValues).contains(column2Value)
&& Arrays.asList(myRowValues).contains(column3Value)
&& Arrays.asList(myRowValues).contains(column4Value)) {
JOptionPane.showMessageDialog(null, "Duplicate, try again.");
}else{
//do something else
}
I only get this output:
run:
Successfully recorded login timestamp
[]
[[Ljava.lang.Object;#35fa3ff2]
[[Ljava.lang.Object;#407c448d, [Ljava.lang.Object;#1e78a60e]
Is there any other alternative than using 2 Dimensional Arrays?
I'd appreciate any help.
Thanks.
IFF your JTable cells contain only Strings, you can define your array as String[][] instead of Object[][] and fill it with your JTable contents using aDestinationTable.getValueAt(j, i).toString().
EDIT: since that's not the case (as per your comment), it's probably better to use a List, like this:
List<List<Object>> objectList = new ArrayList<>();
for (int j = 0; j < 2; j++) {
objectList.add(j, new ArrayList<>());
for (int i = 0; i < 2; i++) {
if (i==0) objectList.get(j).add("string" + j + i);
if (i==1) objectList.get(j).add((double) 37.8346 * j * i);
}
}
System.out.println("OBJECT LIST: "+objectList);
Output:
OBJECT LIST: [[string00, 0.0], [string10, 37.8346]]
Your code should look like this, then:
List<List<Object>> myRowValues = new ArrayList<>();
for (int j = 0; j < myRowCount; j++) {
myRowValues.add(j, new ArrayList<>());
for (int i = 0; i < myColumnCount; i++) {
myRowValues.get(j).add(aDestinationTable.getValueAt(j, i));
}
}
System.out.println(myRowValues);

How to write an excel table starting from the last value?

I am using JXL api. I want to fill an excel table that already have content, like:
123 321 12324
123 321 231
123 321 343
123 321 454
123 321 565
I am trying to write the next value after the fifth line, but I dont know how to do it. I only know how to create and write an excel table if it is empty. And I know how to read it. I was thinking that first I have to read it, and my array which would contain the values of the table would help me to pick the last value of the table then I would write the other values starting from there. I have these methods:
To read:
arquivo = new File("C:\\Users\\maniceto\\Desktop\\arq.xls");
planilha = Workbook.getWorkbook(arquivo);
Sheet[] abas = planilha.getSheets();
aba = planilha.getSheet(0);
matriz = new String[aba.getRows()][aba.getColumns()];
Cell[] cel;
for (int i = 0; i < matriz.length; i++) {
cel = aba.getRow(i);
for (int j = 0; j < matriz[0].length; j++) {
matriz[i][j] = cel[j].getContents();
}
}
System.out.println("Lines " + matriz.length);
System.out.println("Columns " + matriz[0].length);
System.out.println("");
for (int i = 0; i < matriz.length; i++) {
for (int j = 0; j < matriz[0].length; j++) {
System.out.print(matriz[i][j] + "\t");
}
System.out.println("");
}
To write an empty excel table:
WritableWorkbook workbookVazio = Workbook.createWorkbook(file);
WritableSheet sheet1 = workbookVazio.createSheet("First Sheet", 0);
TableModel model = table.getModel();
for (int i = 0; i < model.getColumnCount(); i++) {
Label column = new Label(i, 0, model.getColumnName(i));
sheet1.addCell(column);
}
int j = 0;
for (int i = 0; i < model.getRowCount(); i++) {
for (j = 0; j < model.getColumnCount(); j++) {
Label row = new Label(j, i + 1,
model.getValueAt(i, j).toString());
sheet1.addCell(row);
}
}
workbookVazio.write();
workbookVazio.close();
As stated by rgettman in this question, I would also advise to use Apache POI to handle Excel files with JAVA.
To append values using POI, you just need to get the current number of rows :
int rows = sheet.getPhysicalNumberOfRows();
POI is well documented and you will easily find several code examples on the net.
you could try something like
int lastRowNum = workbookVazio.getSheet("First Sheet").getLastRowNum();
int nextFreeRow = lastRowNum+1;
or you can use Apache POI theres a good tutorial here.

Excel is missing some values while writing

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);

Categories