Insert image in a table's cell using Apache POI's xwpfd - java

I am working on a program that requires writing results to a .docx in a table format. I need to write images from a folder in some of the table cells, which I have been unable to figure out how to do. The solutions I have seen are to insert the image in the document.
Student student = new Student ();
XWPFDocument Document = new XWPFDocument ();
XWPFTable table = document.createTable(20,2);
XWPFTableRow rows =null;
XWPFTableCell cell = null;
for (int i=0; i<20; i++) {
rows = table.getRow(i)
student = studentList.get(i);
//first column
cell = rows.getCell(0);
//add image to this cell. The path to the image can be gotten from student.getImagePath and the image itself in BufferedImage can be gotten from student.getImage
//second column
cell = rows.getCell(1);
cell.setText(student.getDetails);
}

I was able to sort it out. Below is the working code:
Student student = new Student ();
String [] details = {"Detail1: ", "Detail2: ", "Detail3: ", "Detail4: ", "Detail5: "};
FileInputStream fis;
String imageName;
int index;
File file;
XWPFDocument document = new XWPFDocument(); //create table
XWPFTable table;
XWPFParagraph paragraph;
XWPFRun run;
XWPFTableRow rows = null;
XWPFTableCell cell = null;
//Write Hall Name at the top of the word document
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setUnderline(UnderlinePatterns.WORDS);
run.setText("Hall Name: " + hallName);
run.addBreak();
table = document.createTable(rw, cl);
table.getCTTbl().getTblPr().unsetTblBorders();
for (int i=0; i<rw; i++) {
rows = table.getRow(i);
student = studentList.get(i);
//First column
cell = rows.getCell(0);
paragraph = cell.addParagraph();
run = paragraph.createRun();
if (student.getImagePath() == null) {
run.setText("Image Unavailable");
}
else {
fis = new FileInputStream(student.getImagePath());
index = student.getImagePath().lastIndexOf('\\') + 1;
imageName = student.getImagePath().substring(index);
run.addPicture(fis, XWPFDocument.PICTURE_TYPE_JPEG, imageName, Units.toEMU(100), Units.toEMU(100));
}
//Second column
cell = rows.getCell(1);
paragraph = cell.addParagraph();
run = paragraph.createRun();
run.setText(details[0] + student.getRegNumber());
run.addBreak();
run.setText(details[1] + student.getName());
run.addBreak();
run.setText(details[2] + student.getExamNumber());
run.addBreak();
run.setText(details[3] + student.getTableNumber());
run.addBreak();
run.setText(details[4] + student.getLevel());
}

Related

Inserting XWPFTable in between contents

HI I would like to insert a XWPFTable in between some contents. The file is content is fixed and file is taken as input. I need the table to be inserted in the specific field.
like this:
Stack Overflow is a privately held website, the flagship site of the Stack Exchange Network, created in 2008 by Jeff Atwood and Joel Spolsky. Here is the table.
The contents continue.It was created to be a more open alternative to earlier question and answer sites such as Experts-Exchange.
Thanks
The code i have written
public static void main(String[] args) throws IOException {
XWPFDocument document = new XWPFDocument(new FileInputStream(new File("input.docx")));
FileOutputStream out = new FileOutputStream(new File("output.docx"));
XmlCursor cursor = null;
List<IBodyElement> elements = document.getBodyElements();
for (int n = 0; n < elements.size(); n++) {
IBodyElement element = elements.get(n);
if (element instanceof XWPFParagraph) {
XWPFParagraph p1 = (XWPFParagraph) element;
List<XWPFRun> runList = p1.getRuns();
StringBuilder sb = new StringBuilder();
for (XWPFRun run : runList)
sb.append(run.getText(0));
if (sb.toString().contains("Text after which table should be created")) {
cursor= p1.getCTP().newCursor();
break;
}
}
}
XWPFParagraph p = document.insertNewParagraph(cursor);
XWPFTable table = p.getBody().insertNewTbl(cursor);
XWPFTableRow tableRowOne = table.createRow();
//other codes for generating the table
I am getting null pointer exception on creating the row.
Have tested now. My suspicion was right. The cursor was on the wrong place in your code after XWPFParagraph p = document.insertNewParagraph(cursor);. So the XWPFTable table = p.getBody().insertNewTbl(cursor); could not be inserted and was null then.
But there are further problems. If the text was found, we are in the paragraph after which the table shall be placed. So we need moving the cursor to the next paragraph. But what if there is not a next paragraph? Then a new paragraph needs to be created. Fortunately the XmlCursor.toNextSibling flags if it was successful.
Example:
Template:
Code:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth;
import org.apache.xmlbeans.XmlCursor;
import java.math.BigInteger;
public class WordInsertTableInBody {
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("WordTableExample.docx"));
XmlCursor cursor = null;
XWPFParagraph paragraph = null;
XWPFRun run = null;
boolean foundTablePosition = false;
boolean thereWasParagraphAfter = false;
for (IBodyElement element : document.getBodyElements()) {
if (element instanceof XWPFParagraph) {
paragraph = (XWPFParagraph) element;
StringBuilder sb = new StringBuilder();
for (XWPFRun irun : paragraph.getRuns()) {
sb.append(irun.getText(0));
System.out.println(sb);
if (sb.toString().contains("Text after which table should be created")) {
cursor= paragraph.getCTP().newCursor();
thereWasParagraphAfter = cursor.toNextSibling(); // move cursor to next paragraph
//because the table shall be **after** that paragraph
//thereWasParagraphAfter is true if there is a next paragraph, else false
foundTablePosition = true;
}
}
}
if (foundTablePosition) break;
}
if (cursor != null) {
if (thereWasParagraphAfter) {
paragraph = document.insertNewParagraph(cursor);
} else {
paragraph = document.createParagraph();
}
cursor = paragraph.getCTP().newCursor();
XWPFTable table = document.insertNewTbl(cursor);
XWPFTableRow row = table.getRow(0); if (row == null) row = table.createRow();
int twipsPerInch = 1440;
table.getCTTbl().addNewTblGrid().addNewGridCol().setW(BigInteger.valueOf(1*1440));
for (int col = 1 ; col < 4; col++) {
table.getCTTbl().getTblGrid().addNewGridCol().setW(BigInteger.valueOf(1*1440));
}
for (int i = 0; i < 4; i++) {
XWPFTableCell cell = row.getCell(i); if (cell == null) cell = row.createCell();
CTTblWidth tblWidth = cell.getCTTc().addNewTcPr().addNewTcW();
tblWidth.setW(BigInteger.valueOf(1 * twipsPerInch));
tblWidth.setType(STTblWidth.DXA);
if (cell.getParagraphs().size() > 0 ) paragraph = cell.getParagraphs().get(0); else paragraph = cell.addParagraph();
run = paragraph.createRun();
run.setText("Table Cell " + i);
}
}
FileOutputStream out = new FileOutputStream("WordTableExampleNew.docx");
document.write(out);
out.close();
document.close();
}
}
Result:
I am not certain that either of the XWPFDocument.insertTable() methods work correctly. One thing I noticed is that you have:
XWPFParagraph p = document.insertNewParagraph(cursor);
XWPFTable table = p.getBody().insertNewTbl(cursor);
which is equivalent to:
XWPFParagraph p = document.insertNewParagraph(cursor);
XWPFTable table = document.insertNewTbl(cursor);
This leaves me wondering if you have some confusion concerning where a table fits inside a document. Paragraphs and Tables are proper siblings. Paragraphs do not contain tables, though Tables can contain Paragraphs (and other tables) in table cells.
The paragraph body is actually the part that contains the paragraph. This can be a document part, or a header/footer part, or a comment part, etc. But, XWPFParagraph.getBody() does not refer to the contents of the paragraph. Rather, it refers to the paragraph's parent part.

Writing data in an existing worksheet using JXL and Java

I have the code to get data from the worksheet using JXL and Java, but at the end of the process I need to get a data from the page and write to a certain cell in the worksheet.
//reading the worksheet
Workbook workbook = Workbook.getWorkbook(new File("d:/planilha.xls"));
//Indicate the opening of the first worksheet
Sheet sheet = workbook.getSheet(0);
//Count the rows
int linhas = sheet.getRows();
//Start a for loop to scan all rows in the already selected worksheet
for(int i = 1; i < linhas; i++){
//Referencing rows that have content
Cell nome_promocao = sheet.getCell(0, i);
Cell desc_promocao = sheet.getCell(1, i);
Cell tipo_promocao = sheet.getCell(2, i);
Cell dt_inicio = sheet.getCell(3, i);
Cell dt_fim = sheet.getCell(4, i);
Cell aparelho = sheet.getCell(5, i);
Cell idpromo = sheet.getCell(6, i);
//Taking the data from the worksheet
String linhanomepromocao = nome_promocao.getContents();
String linhadescpromocao = desc_promocao.getContents();
String linhatipopromocao = tipo_promocao.getContents();
String linhadtinicio= dt_inicio.getContents();
String linhadtfim = dt_fim.getContents();
String linhaaparelho = aparelho.getContents();
String linhaidpromo = idpromo.getContents();
//Other actions
//Get the id I need on the page and saving in a variable
String numberpromotion = driver.findElement(By.className("link")).getText();
//I need to record this number of the above variable in the corresponding cell (idpromo or linhaidpromo)
Does this provide answer to your question?:
Label label = new Label(6, i, numberpromotion);
sheet.addCell(label);

copy excel sheet(With charts) to another excel sheet

I am using APACHE POI 3.0 to add sheets to existing excel sheet. It works fine.
But as APACHE POI has limitations about making charts, I used a template excel file to create charts, which also worked fine, but this always result in new excel file.
If I have an existing excel sheet and I want to add a sheet, having charts, I am not able to do it. As, when I create charts, I use template file and it always makes a new excel file.
so I was wondering if there is any solution of it of adding sheets to excel, where the sheets have charts
public class TagBrowserSelection
{
private static String[] excelBarPlot_Template = { "","barPlot_1Panel_template.xlsx"};
private static String[] excelPieChart_Template = { "","pieChart_1Panel_template.xlsx"};
private static String[] excelPieAndBarPlot_Template = { "","pieAndBarChart_1Panel_template.xlsx"};
private static String REGEX = "";
static public boolean makeTagBrowserSelection(String strOutputFileName, ArrayList<TagBrowserChildPanel> childList, String sheetName, boolean addSheet, ArrayList<Boolean> chartAttributes)
{
// chart attributes
boolean addBarChart = chartAttributes.get(0);
boolean addPieChart = chartAttributes.get(1);
boolean addNoTag = chartAttributes.get(2);
boolean addZeros = chartAttributes.get(3);
REGEX = "^" + sheetName;
Pattern p = Pattern.compile(REGEX);
String[] templateArray = null;
if (addBarChart && addPieChart)
templateArray = excelPieAndBarPlot_Template;
else if (addBarChart)
templateArray = excelBarPlot_Template;
else if (addPieChart)
templateArray = excelPieChart_Template;
try
{
int number = childList.size();
XSSFWorkbook workbook = null;
XSSFWorkbook wb = null;
XSSFSheet sheet = null;
int col_num = 0;
int row_num = 0;
XSSFRow row = null;
XSSFCell cell = null;
// if adding sheet to existing excel file
if (addSheet)
{
FileInputStream fis = new FileInputStream(new File(strOutputFileName));
workbook = new XSSFWorkbook(fis);
fis.close();
// number of existing sheets in excel file
int numberOfSheets = workbook.getNumberOfSheets();
// check is sheetName exists already
if (isSheetExist(sheetName, workbook))
{
int counter = 1;
for (int ii = 0; ii < numberOfSheets; ii++)
{
Matcher m = p.matcher(workbook.getSheetName(ii));
if (m.find())
counter++;
}
sheetName = sheetName + " (" + counter + ")";
}
}
else
{
workbook = new XSSFWorkbook();
}
======================================================================
// if template file needs to be used(if bar chart/pie chart option is selected)
if (templateArray != null)
{
InputStream is = TagBrowserSelection.class.getClassLoader().getResourceAsStream(templateArray[number]);
wb = new XSSFWorkbook(OPCPackage.open(is));
sheet = wb.getSheetAt(0);
// wb.close();
}
else
{
sheet = workbook.createSheet(sheetName);
}
// Freeze top two row
// sheet.createFreezePane(0, 1, 0, 1);
// Filling up the workbook and performing the row/column formatting
for (TagBrowserChildPanel child : childList)
{
// Check if row is already created before(previous tag category)
row = sheet.getRow(0);
if (row == null)
row = sheet.createRow(0);
// Adding tag category name as header
String tagCategory = child.getSelectedCategory().getName();
cell = row.createCell(col_num);
cell.setCellValue(tagCategory);
row = sheet.getRow(1);
if (row == null)
row = sheet.createRow(1);
// Adding column headers
cell = row.createCell(col_num);
cell.setCellValue("tag");
cell = row.createCell(col_num + 1);
cell.setCellValue("counts");
row_num = 2;
// Adding tag category document summary(name and counts)
ArrayList<TagSummaryItem> tagSummary = child.getTagChartCounts();
for (int i = 0; i < tagSummary.size(); i++)
{
// Check if row is already created before(previous tag category)
row = sheet.getRow(row_num);
if (row == null)
row = sheet.createRow(row_num);
cell = row.createCell(col_num);
if (!addNoTag)
{
if (tagSummary.get(i).m_strTag == "[No Tag]")
continue;
}
if (!addZeros)
{
if (tagSummary.get(i).m_nCount == 0)
continue;
}
cell.setCellValue(tagSummary.get(i).m_strTag);
cell = row.createCell(col_num + 1);
cell.setCellValue(tagSummary.get(i).m_nCount);
row_num++;
}
// auto-size of tag column
sheet.autoSizeColumn(col_num);
col_num = col_num + 3;
}
FileOutputStream out = new FileOutputStream(strOutputFileName);
if (templateArray != null)
{
wb.setSheetName(0, sheetName);
wb.write(out);
wb.close();
}
else
{
workbook.write(out);
workbook.close();
}
out.close();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
Above is my code, its one code. I split into two sections. Section is the one which uses template to make chart excel sheet.
there's the method cloneSheet() in the HSSFWorkbook class. Try it.

Fetching value from webtable and write in excel sheet one by one of each row in a loop

1) I am trying to read the values from the webtable of an appliation and write it into the excel sheet one by one.
2) There are 4 values in each row of the webtable that need to be written to excel sheet, but there are some images in each row that i'm ignoring bu using below code.
text.length()>2
.
3) There will be 200-300 rows in webtable that need to be fetched and written to excel sheet.
This is the code i have tried. But i dont know how to write it into each row of the excel sheet one by one. Please help me in this regard.
//get the table
WebElement statusTable = browser.findElement(By.id("projectstatus"));
//Get all the rows in the table
List<WebElement> allRows = statusTable.findElements(By.tagName("tr"));
//Get the size(row no) of allRows
int rowSize = allRows.size();
System.out.println(rowSize);
for (WebElement row : allRows) {
//Get all cell values in each row
List<WebElement> allCells = row.findElements(By.tagName("td"));
//System.out.println(allCells.size());
if(allCells.size() > 1){
for (WebElement cell : allCells) {
String text = cell.getText();
if(text.length()>2){
String value = cell.getText();
}
}
}
// locate the test xl file
File file = new File("e:\\Testing_emi.xls");
// create input stream
FileInputStream fis = new FileInputStream(file);
// create workbook
HSSFWorkbook wb = new HSSFWorkbook(fis);
// get sheet
HSSFSheet sheet1 = wb.getSheet("Sheet1");
// get rows
HSSFRow row = sheet1.getRow(1);
HSSFCell cellEx = row.getCell(0);
if (cellEx == null) {
cellEx = row.createCell(0);
}
cellEx.setCellValue(value);
//get the table
WebElement statusTable = browser.findElement(By.id("projectstatus"));
//Get all the rows in the table
List<WebElement> allRows = statusTable.findElements(By.tagName("tr"));
//Get the size(row no) of allRows
int rowSize = allRows.size();
System.out.println(rowSize);
// locate the test xls file
File file = new File("e:\\Testing_emi.xls");
// create input stream
FileInputStream fis = new FileInputStream(file);
// create workbook
HSSFWorkbook wb = new HSSFWorkbook(fis);
// get sheet
HSSFSheet sheet1 = wb.getSheet("Sheet1");
// get rows
HSSFRow row;
for (int i=0; i<rowSize; i++)
{
WebElement webRow = allRows.get(i);
//Get all cell values in each row
List<WebElement> allCells = webRow.findElements(By.tagName("td"));
//System.out.println(allCells.size());
if(allCells.size() > 1)
{
HSSFRow excelRow = sheet1.createRow(i);
for (int j=0; j<allCells.size(); j++)
{
WebElement webCell = allCells.get(j);
String text = webCell.getText();
if(text.length()>2)
{
Cell excelCell = excelRow.createCell();
excelCell.setValue(webCell.getText());
}
}
}
}
sheet1.close();
Read the values from the Web Table of an application and write it in to the excel sheet one by one.There are 5 values in each row of the Web Table and that need to written in Excel sheet. Below is the working code.
System.setProperty("webdriver.chrome.driver","C:\\Users\\Documents\\Selenium jars\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://cosmocode.io/automation-practice-webtable/");
WebElement table = driver.findElement(By.xpath("//*[#id='countries']/tbody"));
List<WebElement> rows = table.findElements(By.tagName("tr"));
int rowcount = rows.size();
FileOutputStream fis = new FileOutputStream(new File("C:\\Users\\Documents\\Selenium\\output.xlsx"));
XSSFWorkbook wb = new XSSFWorkbook();
XSSFSheet sh = wb.createSheet("First Sheet");
for (int row = 0; row < rowcount; row++) {
List<WebElement> columns_inrow = rows.get(row).findElements(By.tagName("td"));
int columns_count = columns_inrow.size();
System.out.println("Number of cells in Row " + row + " are " + columns_count);
Row ro = sh.createRow(row);
for (int column = 0; column < columns_count; column++) {
String celltext = columns_inrow.get(column).getText();
System.out.println(
"Cell Value of row number " + row + " and column number " + column + " Is " + celltext);
ro.createCell(column).setCellValue(celltext);
}
System.out.println("===========================");
}
wb.write(fis);
wb.close();
}

How can I get the location of picture in a xlsx file by using Apache POI

I can get the picture file, but I don't konw how to get the location of picture.
I can't find the correct method in POI.
InputStream is= new FileInputStream("test.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(is);
List<PictureData> list = (List)workbook.getAllPictures();
int i = 0;
System.out.println(list.size());
for(Iterator<PictureData> it = list.iterator(); it.hasNext(); ){
PictureData pd = it.next();
savePic(i, pd);
i++;
}
There is another way to get the position information from XSSFSheet.
XSSFSheet sheet = workBook.getSheetAt(0);
XSSFDrawing drawing = sheet.createDrawingPatriarch(); // I know it is ugly, actually you get the actual instance here
for (XSSFShape shape : drawing.getShapes()) {
if (shape instanceof XSSFPicture) {
XSSFPicture picture = (XSSFPicture) shape;
XSSFPictureData xssfPictureData = picture.getPictureData();
ClientAnchor anchor = picture.getPreferredSize();
int row1 = anchor.getRow1();
int row2 = anchor.getRow2();
int col1 = anchor.getCol1();
int col2 = anchor.getCol2();
System.out.println("Row1: " + row1 + " Row2: " + row2);
System.out.println("Column1: " + col1 + " Column2: " + col2);
// Saving the file
String ext = xssfPictureData.suggestFileExtension();
byte[] data = xssfPictureData.getData();
String filePath = "C:\\..\\Images\\" + xssfPictureData.getPackagePart().getPartName();
try (FileOutputStream os = new FileOutputStream(filePath)) {
os.write(data);
os.flush();
}
}
}
This is how getAllPictures() is implemented: Query the XSSFSheet (inSheet) with getRelations() and look for XSSFDrawing.
The CTDrawing class provides several methods to get the anchor of the pictures.
for(POIXMLDocumentPart dr : inSheet.getRelations()) {
if(dr instanceof XSSFDrawing) {
CTDrawing ctDrawing = ((XSSFDrawing) dr).getCTDrawing();
for (CTTwoCellAnchor anchor: ctDrawing.getTwoCellAnchorList()) {
CTMarker from = anchor.getFrom();
int row1 = from.getRow();
int col1 = from.getCol();
CTMarker to = anchor.getTo();
int row2 = to.getRow();
int col2 = to.getCol();
// do something here
}
}
}

Categories

Resources