I want to convert my excel file as well as its entites(charts, tables, images) to jpeg/png images. Currently using aspose for that. Here is my code
public static int excelToImages(final String sourceFilePath, final String outFilePrefix) throws Exception {
int noOfImages = 0;
Workbook workbook = getWorkbook(sourceFilePath);
List<Worksheet> worksheets = getAllWorksheets(workbook);
if (worksheets != null) {
for (Worksheet worksheet : worksheets) {
if (worksheet.getCells().getCount() > 0) {
String outFilePath = FileUtils.getAbsoluteFilePath(outFilePrefix + (noOfImages++));
SheetRender sr = new SheetRender(worksheet, getImageOrPrintOptions());
sr.toImage(0, outFilePath);
}
}
}
return noOfImages;
}
private static ImageOrPrintOptions getImageOrPrintOptions() {
ImageOrPrintOptions imgOptions = new ImageOrPrintOptions();
imgOptions.setImageFormat(ImageFormat.getJpeg());
imgOptions.setOnePagePerSheet(true);
return imgOptions;
}
private static List<Worksheet> getAllWorksheets(final Workbook workbook) {
List<Worksheet> worksheets = new ArrayList<Worksheet>();
WorksheetCollection worksheetCollection = workbook.getWorksheets();
for (int i = 0; i < worksheetCollection.getCount(); i++) {
worksheets.add(worksheetCollection.get(i));
}
return worksheets;
}
My problem is that size of output image is either split into multiple A4 size or single 1 sheet depends upon the value of
imgOptions.setOnePagePerSheet(true);
Can anybody tell me how I can customize the size of output image file?
You can try it with imgOptions.setOnlyArea(true);. That will set the size of the image to the minimal that's needed to put everything to the image. But I'm not sure if the generated image is split into A4 parts.
Related
I have a placeholder image in my docx file and I want to replace it with new image. The problem is - the placeholder image has an attribute "in front of text", but the new image has not. As a result the alignment breaks. Here is my code snippet and the docx with placeholder and the resulting docx.
.......
replaceImage(doc, "Рисунок 1", qr, 50, 50);
ByteArrayOutputStream out = new ByteArrayOutputStream();
doc.write(out);
out.close();
return out.toByteArray();
}
}
public XWPFDocument replaceImage(XWPFDocument document, String imageOldName, byte[] newImage, int newImageWidth, int newImageHeight) throws Exception {
try {
int imageParagraphPos = -1;
XWPFParagraph imageParagraph = null;
List<IBodyElement> documentElements = document.getBodyElements();
for (IBodyElement documentElement : documentElements) {
imageParagraphPos++;
if (documentElement instanceof XWPFParagraph) {
imageParagraph = (XWPFParagraph) documentElement;
if (imageParagraph.getCTP() != null && imageParagraph.getCTP().toString().trim().contains(imageOldName)) {
break;
}
}
}
if (imageParagraph == null) {
throw new Exception("Unable to replace image data due to the exception:\n"
+ "'" + imageOldName + "' not found in in document.");
}
ParagraphAlignment oldImageAlignment = imageParagraph.getAlignment();
// remove old image
boolean isDeleted = document.removeBodyElement(imageParagraphPos);
// now add new image
XWPFParagraph newImageParagraph = document.createParagraph();
XWPFRun newImageRun = newImageParagraph.createRun();
newImageParagraph.setAlignment(oldImageAlignment);
try (InputStream is = new ByteArrayInputStream(newImage)) {
newImageRun.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, "qr",
Units.toEMU(newImageWidth), Units.toEMU(newImageHeight));
}
// set new image at the old image position
document.setParagraph(newImageParagraph, imageParagraphPos);
// NOW REMOVE REDUNDANT IMAGE FORM THE END OF DOCUMENT
document.removeBodyElement(document.getBodyElements().size() - 1);
return document;
} catch (Exception e) {
throw new Exception("Unable to replace image '" + imageOldName + "' due to the exception:\n" + e);
}
}
The image with placeholder:
enter image description here
The resulting image:
enter image description here
To replace picture templates in Microsoft Word there is no need to delete them.
The storage is as so:
The embedded media is stored as binary file. This is the picture data (XWPFPictureData). In the document a picture element (XWPFPicture) links to that picture data.
The XWPFPicture has settings for position, size and text flow. These dont need to be changed.
The changing is needed in XWPFPictureData. There one can replace the old binary content with the new.
So the need is to find the XWPFPicture in the document. There is a non visual picture name stored while inserting the picture in the document. So if one knows that name, then this could be a criteriea to find the picture.
If found one can get the XWPFPictureData from found XWPFPicture. There is method XWPFPicture.getPictureDatato do so. Then one can replace the old binary content of XWPFPictureData with the new. XWPFPictureData is a package part. So it has PackagePart.getOutputStream to get an output stream to write to.
Following complete example shows that all.
The source.docx needs to have an embedded picture named "QRTemplate.jpg". This is the name of the source file used while inserting the picture into Word document using Word GUI. And there needs to be a file QR.jpg which contains the new content.
The result.docx then has all pictures named "QRTemplate.jpg" replaced with the content of the given file QR.jpg.
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
public class WordReplacePictureData {
static XWPFPicture getPictureByName(XWPFRun run, String pictureName) {
if (pictureName == null) return null;
for (XWPFPicture picture : run.getEmbeddedPictures()) {
String nonVisualPictureName = picture.getCTPicture().getNvPicPr().getCNvPr().getName();
if (pictureName.equals(nonVisualPictureName)) {
return picture;
}
}
return null;
}
static void replacePictureData(XWPFPictureData source, String pictureResultPath) {
try ( FileInputStream in = new FileInputStream(pictureResultPath);
OutputStream out = source.getPackagePart().getOutputStream();
) {
byte[] buffer = new byte[2048];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
static void replacePicture(XWPFRun run, String pictureName, String pictureResultPath) {
XWPFPicture picture = getPictureByName(run, pictureName);
if (picture != null) {
XWPFPictureData source = picture.getPictureData();
replacePictureData(source, pictureResultPath);
}
}
public static void main(String[] args) throws Exception {
String templatePath = "./source.docx";
String resultPath = "./result.docx";
String pictureTemplateName = "QRTemplate.jpg";
String pictureResultPath = "./QR.jpg";
try ( XWPFDocument document = new XWPFDocument(new FileInputStream(templatePath));
FileOutputStream out = new FileOutputStream(resultPath);
) {
for (IBodyElement bodyElement : document.getBodyElements()) {
if (bodyElement instanceof XWPFParagraph) {
XWPFParagraph paragraph = (XWPFParagraph)bodyElement;
for (XWPFRun run : paragraph.getRuns()) {
replacePicture(run, pictureTemplateName, pictureResultPath);
}
}
}
document.write(out);
}
}
}
I have a dirty workaround. Since the text block on the right side of the image is static, I replaced the text with screen-shot on the original docx. And now, when the placeholder image been substituted by the new image, everything is rendered as expected.
I have it currently working so that my application is generating the content, then saving the information into an excel file, this is working as expected using the below code
public void writeExcel(ClassManager cm, String fn, ErrorManager em) throws FileNotFoundException, IOException {
// Get classes
classes = cm.getClasses();
String fileName = (!"".equals(fn)) ? fn : "temp.xlsx";
// Create Rows
setupRows();
File currDir = new File(".");
String path = currDir.getAbsolutePath();
String fileLocation = path.substring(0, path.length() - 1) + fileName;
FileOutputStream outputStream = new FileOutputStream(fileLocation);
workbook.write(outputStream);
outputStream.close();
workbook.close();
}
the setupRow function calls several other functions, all setup the same as below
public void setupRowTemplateName() {
int start = 2;
Row row = sheet.createRow(1);
for (int i = 0; i < classes.size(); i++) {
// Get class and template details
Classes c = classes.get(i);
Template t = c.getTemplate();
// Create cell
Cell cell = row.createCell(start);
// Set contents
if(t != null) {
cell.setCellValue(t.getName());
}
start++;
}
}
I'm trying to adjust the saving so that it takes an excel file, adds the information to that, then saves as a new file (i.e: Take file "Codes Template.xlsx", add data, save as another filename.
So far I have
public void writeExcelReplace(ClassManager cm, String fn, ErrorManager em) throws FileNotFoundException, IOException {
File currDir = new File(".");
String path = currDir.getAbsolutePath();
String fileLocationOpen = path.substring(0, path.length() - 1) + "Codes Template.xlsx";
FileInputStream inputStream = new FileInputStream(new File(fileLocationOpen));
workbook = WorkbookFactory.create(inputStream);
sheet = workbook.getSheetAt(0);
// Get classes
classes = cm.getClasses();
String fileName = (!"".equals(fn)) ? fn : "temp.xlsx";
// Create Rows
setupRows();
String fileLocation = path.substring(0, path.length() - 1) + fileName;
inputStream.close();
FileOutputStream outputStream = new FileOutputStream(fileLocation);
workbook.write(outputStream);
outputStream.close();
workbook.close();
}
This is taking the content from the "template" file and saving it to the new file, but none of the content from setupRows is being added
I have three images I need to insert in three different sheets by using the Poi Apache library but all 3 images get inserted in the last sheet, please advise me what needs to be done to insert the images in different sheets. Help is appreciated. ---------------------------------------------------------------------------------------------------------------------
public class Img2xls {
public static byte[] bytes;
public static HSSFWorkbook my_workbook;
public static HSSFSheet my_sheet;
public static InputStream my_banner_image;
private static HSSFPatriarch drawing;
// Initializing employees data to insert into the excel file
public static void main(String[] args) throws IOException, InvalidFormatException{
String path1 = "C:\\Users\\ELCOT\\Pictures\\screen1.png";
String path2 = "C:\\Users\\ELCOT\\Pictures\\screen2.png";
String path3 = "C:\\Users\\ELCOT\\Pictures\\screen1.png";
/* Create a Workbook and Worksheet */
my_workbook = new HSSFWorkbook();
my_sheet = my_workbook.createSheet("Vista");
my_sheet = my_workbook.createSheet("Hub2");
my_sheet = my_workbook.createSheet("D42");
HSSFSheet my_sheet1 = my_sheet;
/* Create the drawing container */
drawing = my_sheet1.createDrawingPatriarch();
getImage(path1,0);
getImage(path2,40);
getImage(path3,80);
/* Write changes to the workbook */
FileOutputStream out = new FileOutputStream(new File("excel_insert_image_example.xls"));
my_workbook.write(out);
out.close();
}
public static void getImage(String img,int i) throws FileNotFoundException, IOException{
Row headerRow = my_sheet.createRow(i);
Cell cell = headerRow.createCell(0);
cell.setCellValue("Server 1");
my_sheet.autoSizeColumn(0);
/* Read the input image into InputStream */
my_banner_image = new FileInputStream(img);
/* Convert Image to byte array */
bytes = IOUtils.toByteArray(my_banner_image);
/* Add Picture to workbook and get a index for the picture */
int my_picture_id = my_workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG);
//int my_picture_id = my_workbook.addPictur
/* Close Input Stream */
my_banner_image.close();
/* Create an anchor point */
ClientAnchor my_anchor = new HSSFClientAnchor();
/* Define top left corner, and we can resize picture suitable from there */
my_anchor.setCol1(2);
my_anchor.setRow1(i);
/* Invoke createPicture and pass the anchor point and ID */
HSSFPicture my_picture = drawing.createPicture(my_anchor, my_picture_id);
/* Call resize method, which resizes the image */
my_picture.resize();
}
}
As Modus already mentioned, you are creating one variable, and without using it, you are updating its value again and again.
Understand it with very basic example;
int x
x = 5;
x = 10;
x = 20;
Now what you are expecting, what will be value of x if we will print it... It will be 20... not 5 and 10 and 20 at once. You are doing the same with my_sheet. You are creating three sheets and assigning them to my_sheet. The newly created instance will replace the previous one and at the end when you will use it, it will be the last instance only.
my_workbook = new HSSFWorkbook();
my_sheet = my_workbook.createSheet("Vista");
my_sheet = my_workbook.createSheet("Hub2");
my_sheet = my_workbook.createSheet("D42");
HSSFSheet my_sheet1 = my_sheet;
Update:
The solution is create one method which takes Three parameters say.
public void insertImageInSheet(String sheetName, String path, int number){
//Now first create new sheet in workbook
Sheet newSheet= my_workbook.createSheet(sheetName);
drawing = newSheet.createDrawingPatriarch();
//not sure what second parameter is right now I have given it a name as number
getImage(path,number);
}
//and then use this method three times
insertImageInSheet("Vista", path1, 0);
insertImageInSheet("Hub2", path2, 40);
insertImageInSheet("D42", path3, 80);
//Now write the wrokbook from output stream
/* Write changes to the workbook */
FileOutputStream out = new FileOutputStream(new File("excel_insert_image_example.xls"));
my_workbook.write(out);
out.close();
I am using Java 8, excel and apache poi for my project. There are certain cell values that I am interested in extracting from excel using java. I am trying to detect text which is strikeout in the excel cells, but the format of text is little different that is why I am facing some problems.
Below is how data laid out in my excel sheet:
After extacting this data from excel, I always save it in string arraylist format like this a = [text 1, text 2, text 3]. code is mentioned below if you want to see how I am storing data in this arraylist.
What I want:
I want to ignore all those texts which are strikeout, so in above case I expect to have output like this [text 2, text 3] for first picture and second picture.
What I tried:
For the sake of just detecting strikeout values, I tried below code first:
XSSFRichTextString text = new XSSFRichTextString(a.get(0));
XSSFFont font = text.getFontAtIndex(0);
Boolean font_striked = font.getStrikeout();
but above code is not working as font_striked returns null, it must return true or false
The code which partially works in my case on single line cell values is:
boolean striked_out = sheet.getRow(row_index).getCell(column_index).getCellStyle().
getFont().getStrikeout();
This code only works if there is single line value in the cell and not with bullet list as shown above. It fails as it is not made for such kind of text.
P.S
I believe that if somehow I am able to detect even a single strikeout string in bullet points from arraylist, I can make it work for all the data.
As per the answer below I have updated my question adding following code to show how I make my string arraylist
How I convert data in excel into Arraylist:
String value_header = cell.getStringCellValue();
String[] newline_split = value_header.split("-");
for (int i = 0; i < newline_split.length; i++){
final_values = newline_split[i].
replace("\n"," ").replaceAll("\\s{2,}", " ").trim();
XSSFRichTextString text = new XSSFRichTextString(final_values);
XSSFFont font = text.getFontAtIndex(0);
Boolean font_striked = font.getStrikeout();
} // for ends here
You will need to get the RichTextString first, then go through all FormattingRuns, check whether it is stroked out and only if not, then get the appropriated substring and put it into the List:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.CellType.*;
import org.apache.poi.xssf.usermodel.*;
import java.io.FileInputStream;
import java.util.List;
import java.util.ArrayList;
class ReadExcelRichTextCells {
public static void main(String[] args) throws Exception {
Workbook wb = WorkbookFactory.create(new FileInputStream("ExcelRichTextCells.xlsx"));
Sheet sheet = wb.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
switch (cell.getCellTypeEnum()) {
case STRING:
XSSFRichTextString richtextstring = (XSSFRichTextString)cell.getRichStringCellValue();
String textstring = richtextstring.getString();
List<String> textparts = new ArrayList<String>();
if (richtextstring.hasFormatting()) {
for (int i = 0; i < richtextstring.numFormattingRuns(); i++) {
if (richtextstring.getFontOfFormattingRun(i)==null || !richtextstring.getFontOfFormattingRun(i).getStrikeout()) {
int indexofformattingrun = richtextstring.getIndexOfFormattingRun(i);
String textpart = textstring.substring(indexofformattingrun,
indexofformattingrun + richtextstring.getLengthOfFormattingRun(i));
String[] textpart_split = textpart.split("-");
for (int j = 0; j < textpart_split.length; j++){
String text = textpart_split[j].replace("\n", "").trim();
if (!"".equals(text)) textparts.add(text);
}
}
}
} else {
textparts.add(textstring);
}
System.out.println(textparts);
break;
//...
default:
System.out.println("default cell"); //should never occur
}
}
}
wb.close();
}
}
This is how to get the strikethrough in Excel with VBA:
Public Sub IsMyActivecellStriked()
Debug.Print ActiveCell.Font.Strikethrough
End Sub
If you have something like this:
Then the you should find a way to access the characters and check for them. Like this:
Option Explicit
Public Sub TestMe()
Dim strRange As String
Dim varArr As Variant
Dim varStr As Variant
Dim lngStart As Long
Dim lngEnd As Long
strRange = [a1]
varArr = Split(strRange, Chr(10))
For Each varStr In varArr
lngStart = InStr(1, strRange, varStr)
Debug.Print [a1].Characters(Start:=lngStart, Length:=Len(varStr)).Font.Strikethrough
Debug.Print [a1].Characters(Start:=lngStart, Length:=Len(varStr)).Text
Next varStr
End Sub
This will give you the following in the immediate window:
False
aaa
True
bbb
True
ccc
False
ddd
This should be possible to be translated into Java with the POI library.
As per I understanding above question Question (plz Correct me if I am wrong..!)
It should show whether your text in cell is strikethrough or not. ( TRUE or FALSE)
Below I have created a demo with that :
public class ApachePOI {
public static void main(String[] args) {
//Using workbook
XSSFWorkbook workbook;
try {
//Access excel file as workbook
workbook = new XSSFWorkbook(new FileInputStream(new File("/testExcelfile.xlsx")));
// first sheet of excel file
XSSFSheet xssfFirstSheet = workbook.getSheetAt(0);
//Check for A1 cell that strikethrough or not
boolean strikedOutTextStatus = xssfFirstSheet.getRow(0).getCell(0).getCellStyle().getFont().getStrikeout();
//print status of A1 cell text
System.out.println(strikedOutTextStatus);
// UPDATED CODE
if(strikedOutTextStatus){
String cellStringValue = xssfFirstSheet.getRow(0).getCell(0).getStringCellValue();
System.out.println("cell Value : "+cellStringValue.replace("-", "").replace(" ", ""));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
i am trying to upload a excel document with multiple sheets
e.g file name: payroll that contains
sheet 0
sheet 1 and etc....
and i have a multiple database table like table 1, table 2 and etc.....
Now i am trying for map sheet 0 to table 1
sheet 1 for table 2 and etc using java
i am already using single sheet to one table
e.g code:
/**
*
*/
private static final long serialVersionUID = 1L;
public File file;
private int totalRecords=0;
private int successRecords=0;
private int failureRecords=0;
private String totalMsg="Total No. of records processed :";
private String successMsg="No. of records succeeded :";
private String failureMsg="No. of records failed:";
#SuppressWarnings("deprecation")
public OutputStream receiveUpload(String filename, String mimeType) {
// Create upload stream
FileOutputStream fos = null; // Output stream to write to
try {
// Open the file for writing.
file = new File("" + filename);
fos = new FileOutputStream(file);
} catch (final java.io.FileNotFoundException e) {
UI.getCurrent().showNotification(
"Could not open file<br/>", e.getMessage(),
Notification.TYPE_ERROR_MESSAGE);
return null;
}
return fos; // Return the output stream to write to
}
public void uploadSucceeded(SucceededEvent event) {
// Show the uploaded file in the image viewer
try{
Session session = com.systems.payrolladmin.PayrolladminMainUI.sf.openSession();
session.beginTransaction();
//File excel = new File(FILE_PATH);
FileInputStream fis = new FileInputStream(file);
#SuppressWarnings("resource")
XSSFWorkbook book = new XSSFWorkbook(fis);
XSSFSheet sheet = book.getSheetAt(0);
Row row;
ArrayList<Resignee> ErrorDataList2 = new ArrayList<Resignee>();
int LastRowNum=sheet.getLastRowNum();
for(int i=1; i<=LastRowNum; i++){
row = sheet.getRow(i);
String vempId1 = row.getCell(1).getStringCellValue();
Date vdor1=row.getCell(3).getDateCellValue();
Date vdorr=row.getCell(4).getDateCellValue();
String vRemark = row.getCell(5).getStringCellValue();
int a=5;
int b=5;
if(a==b)
{
Resignee resobj = new Resignee();
resobj.setEmpId(vempId1);
resobj.setDOR(vdor1);
resobj.setDOReliv(vdorr);
resobj.setRemarks(vRemark);
session.save(resobj);
resobj=null;
successRecords++;
}else{
Resignee error = new Resignee();
error.setEmpId(vempId1);
error.setDOR(vdor1);
error.setDOReliv(vdorr);
error.setRemarks(vRemark);
error.setRemarks(vRemark);
ErrorDataList2.add(error);
error=null;
failureRecords++;
}
totalRecords++;
}
session.getTransaction().commit();
session.close();
fis.close();
//write to excel
#SuppressWarnings("resource")
XSSFWorkbook workbook = new XSSFWorkbook();
XSSFSheet spreadsheet = workbook.createSheet("employe db");
XSSFRow xrow=spreadsheet.createRow(0);
XSSFCell cell;
cell=xrow.createCell(0);
cell.setCellValue("EMPLOYEE ID");
cell=xrow.createCell(1);
cell.setCellValue("DOR");
cell=xrow.createCell(2);
cell.setCellValue("DORELIEVE");
cell=xrow.createCell(3);
cell.setCellValue("REMARKS");
int i=1;
for (Resignee nobj : ErrorDataList2) {
xrow=spreadsheet.createRow(i);
cell=xrow.createCell(0);
cell.setCellValue(nobj.getEmpId());
cell=xrow.createCell(1);
cell.setCellValue(nobj.getDOR());
cell=xrow.createCell(2);
cell.setCellValue(nobj.getDOReliv());
cell=xrow.createCell(3);
cell.setCellValue(nobj.getRemarks());
i++;
}
FileOutputStream out = new FileOutputStream(
new File("F:\\Error Excel\\ResingeeError.xlsx"));
workbook.write(out);
out.close();
Your question makes it sound like your code is working for a single sheet. If that is true, then the line that gets the first sheet,
XSSFSheet sheet = book.getSheetAt(0);
can be updated to look at multiple sheets as shown in this question Use
book.getNumberOfSheets();
to get the number of sheets in the workbook and then process each separately was you are already doing with sheet 0