0

I am working on Apache POI to extract data from MSEcxel files. What I need to do is to combine selective rows into a single string and generate QR code and further generate a word document and put this data (both generated string and QR code) into two columns of a table. What I need to get is to skip rows which don't fit to the required information.

I am using Apache POI to read excel files as follows

private Workbook workbook;
if(filePath.endsWith(".xls")) {
    workbook = new HSSFWorkbook(excelInputFile)
} else if(filePath.endsWith(".xlsx")) {
        workbook = new XSSFWorkbook(excelInputFile);
}

XSSFSheet sheet = workbook.getSheetAt(0);
Iterator<Row> excelRowIterator = sheet.iterator();
            
List<String> outputHeadings = new ArrayList<>();
outputHeadings.add("Data"); outputHeadings.add("QR Code");
int j = 0;
XWPFTable tab = document.createTable();  
XWPFTableRow wordTableRow = tab.getRow(j); // First row  
wordTableRow.getCell(0).setText(outputHeadings.get(0));
wordTableRow.addNewTableCell().setText(outputHeadings.get(1));

List<String> excelFileHeadings = new ArrayList<>();
Row heading = excelRowIterator.next();
Iterator<Cell> headingIterator = heading.cellIterator();
excelFileHeadings.clear();
boolean qrCodeFormat = false;
int k = 0, qrCodeCellNo = 0;
while(headingIterator.hasNext()) {
    Cell cellHeader = headingIterator.next();
    String headerText = cellHeader.getStringCellValue();
    if(headerText.equals("QR Code")) {
        qrCodeFormat = true;
        qrCodeCellNo = k;
    }
    excelFileHeadings.add(headerText);
    k++;
}
if(!qrCodeFormat) {
    throw new IOException("The file has not been formatted! Please format the file properly and then proceed.");
}

while (excelRowIterator.hasNext()) {
     Row inputDataRow = excelRowIterator.next();

     Iterator<Cell> cellIterator = inputDataRow.cellIterator();
     String excelRow = "";

     int i = 0;
     boolean generateQRCodeForThisRow = false;
     String cellText = "";
     
     while (cellIterator.hasNext()) {
         Cell cell = cellIterator.next();
         CellType cellType = cell.getCellType();

         switch (cellType) {

             case NUMERIC:
              cellText = excelFileHeadings.get(i++) + ": " + (int)cell.getNumericCellValue();
              excelRow += cellText + "\r\n ";
              tableText(wordTableRow.getCell(0).getParagraphs(), cellText);
          
              break;

            case STRING:
              cellText = cell.getStringCellValue();
              if(i == qrCodeCellNo) {
                 i ++;
                 if(cellText.equals("yes")) {
                     generateQRCodeForThisRow = true;
                     wordTableRow = tab.createRow(); // First row
                 }
                 continue;
              }

              cellText = excelFileHeadings.get(i++) + ": " + cell.getStringCellValue();
              excelRow += cellText + "\r\n";
              tableText(wordTableRow.getCell(0).getParagraphs(), cellText);
              break;

        default:
          break;
              }
       }
       System.out.println(excelRow);

       if(generateQRCodeForThisRow) {
        XWPFParagraph paragraph = wordTableRow.getCell(1).addParagraph();
        XWPFRun run = paragraph.createRun();
         generateQRcode(excelRow, charset, 100, 100, run);
       }
       j++;
  }

            // Closing file output streams
            document.write(wordOutputFile);

private static void tableText(List<XWPFParagraph> paragraph, String text) {
    XWPFRun run = paragraph.get(0).createRun();
    run.setFontSize(14);
    run.setFontFamily("Times New Roman");
    run.setText(text);
    run.addBreak();
}

public static void generateQRcode(String data, String charset,
        int h, int w, XWPFRun run) throws WriterException, IOException, InvalidFormatException {
    BitMatrix matrix = new MultiFormatWriter().encode(
            new String(data.getBytes(charset), charset),
            BarcodeFormat.QR_CODE, w, h);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    MatrixToImageWriter.writeToStream(matrix, "png", baos);
    
    byte[] dataBytes = baos.toByteArray();
    
    ByteArrayInputStream inStreambj = new ByteArrayInputStream(dataBytes);
    BufferedImage newImage = ImageIO.read(inStreambj);
    ImageIO.write(newImage, "png", new File("temp.png") );
    
    FileInputStream fis = new FileInputStream("temp.png");
    run.addPicture(fis, XWPFDocument.PICTURE_TYPE_JPEG, "temp",
            Units.toEMU(w), Units.toEMU(h));
    
    baos.close();
    inStreambj.close();
    fis.close();
        

}

I have manually put a cell in name QR Code and put a value yes under all the rows which I want to process and get their QR code. This way I am getting the job done. But I want to generalize it by giving some intelligence to it. I need to get rid of the QR Code column with "yes" written as a value.

input excel file

Output in msword file

Any help in this regard will be highly appreciated.

Thank you

Ameer Moaaviah
  • 1,530
  • 12
  • 27
  • On what basis do you want to decide if you should skip creating QR? Instead of the flag generateQRCodeForThisRow can you write a method validateXXX() which returns boolean and accepts parameter on basis of which you can write logic to whether write QR or not. – Jishnu Prathap Nov 03 '22 at 11:11
  • Sorry, it's not clear to me what exactly your problem is. – vanje Nov 03 '22 at 13:32

0 Answers0