Different Leading for specific page in itext 7 - java

I can set diferent setFixedLeading on specific page.
First i add All paragraphs in list then with help recursive i calculate e height of each paragraph and compare with document height, then i add it to div.
But it dont work.
Maybe there is another way?
public static void main(String[] args) throws FileNotFoundException {
PdfDocument pdf = new PdfDocument(new PdfWriter(DEST));
Document document = new Document(pdf);
pdf.setDefaultPageSize(PageSize.A5);
float bottomMarin = 0;
document.setMargins(0, 25, bottomMarin, 25);
Div div = new Div();
div.setPadding(0);
div.setMargin(0);
maxHeight = document.getPdfDocument().getDefaultPageSize().getHeight()- bottomMarin ;/* (mainPdf_model.getLeftMargin() +mainPdf_model.getRightMargin());*/
String line = "Hello! Welcome to iTextPdf";
List<Paragraph> paragraphs = new ArrayList<>();
for (int i = 0; i < 130; i++) {
Paragraph element = new Paragraph();
element.add(line + " " + i);
element.setMargin(0);
element.setPadding(0);
element.setFixedLeading(100);
paragraphs.add(element);
}
getListParagraphOnPage(paragraphs, document, 1);
Map<Integer, List<Paragraph>> listParagraphOnPage = paragraph;
listParagraphOnPage.forEach((k,v)->{
if(k ==1){
for(Paragraph paragraph : v){
paragraph.setFixedLeading(120);
paragraph.setBackgroundColor(red);
div.add(paragraph);
}
}
if(k ==2){
for(Paragraph paragraph : v){
paragraph.setFixedLeading(150);
paragraph.setBackgroundColor(yellow);
div.add(paragraph);
}
}
if(k ==3){
for(Paragraph paragraph : v){
paragraph.setFixedLeading(30);
paragraph.setBackgroundColor(green);
div.add(paragraph);
}
}
});
Map<Integer, List<Paragraph>> paragraph = new HashMap<>();
document.add(div);
document.close();
}
static Map<Integer,List<Paragraph>> paragraph = new HashMap<>();
//This is a method that is created in the map, in which paragraphs are placed with a certain Leading
public static Map<Integer,List<Paragraph>> getListParagraphOnPage(List<Paragraph> paragraphs, Document document,int page){
float height = 0;
List<Paragraph> ps = new ArrayList<>();
for(Paragraph par: paragraphs){
if(page==1){
par.setFixedLeading(120);
}else if(page==2){
par.setFixedLeading(150);
}else if(page==3){
par.setFixedLeading(30);
}
IRenderer rendererSubTree = par.createRendererSubTree();
LayoutResult result = rendererSubTree.setParent(document.getRenderer()).
layout(new LayoutContext(new LayoutArea(1, new Rectangle(10000, 1000))));
height+=result.getOccupiedArea().getBBox().getHeight();
if(height<maxHeight){
ps.add(par);
}else {
var pageCurrent = page;
paragraph.put(page,ps);
int size = paragraph.get(pageCurrent).size();
page++;
return getListParagraphOnPage(paragraphs.subList(size,paragraphs.size()),document,page);
}
}
return paragraph;
}

Related

One Row in One Page: Boxable

This is the code for this issue for you to check if there is any problem in the code.
Now the problem is when I limit the rows to 45 (this number fits in one page) every row will print in one page.
But, If I don't limit the rows and the row size (approximately 100-200), every row goes to new page in the PDF. The PDF page number goes to approximately equal to row numbers.
I have opened this issue in Boxable's git but it's not active so I came for help here.
Following are the files generated in both conditions:
LimitTemp.pdf
noLimitTemp.pdf
public class CSVtoPDF {
private float marginBetweenYElements = 10;
private float titleFontSize = 18;
private float fontSize = 8;
private float headerFontSize = 12;
private float header1FontSize = 14;
private float header2FontSize = 12;
private float headerCellHeight = 19;
private float dataCellHeight = 12;
private PDFont font = PDType1Font.HELVETICA;
private PDFont headerFont = PDType1Font.TIMES_BOLD;
List filteredData = new ArrayList();
ReportSettings rs = new ReportSettings();
String filePath, destPath, header1, header2, filename;
public CSVtoPDF(List data, Audit audit) throws IOException {
this.filteredData = data;
Date liveDate = new Date();
SimpleDateFormat format= new SimpleDateFormat("YYYY-MM-DD HH:mm:ss");
liveDate = Calendar.getInstance().getTime();
float headerCellHeight = 18;
PDDocument doc = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
//page.setMediaBox(new PDRectangle(PDRectangle.A4.getHeight(),
// PDRectangle.A4.getWidth()));
PDPageContentStream cos = new PDPageContentStream(doc, page);
/* Add page to PDDocument */
doc.addPage(page);
System.out.println("Inside Main csvtopdf");
//Draw Header
Preferences prefs = Preferences.userRoot().node(this.getClass().getName());
try {
String[] keys = prefs.keys();
//destPath = prefs.get("destpath", rs.getDestPath());
//filename = prefs.get("file_name", rs.getFileName());
//header1 = prefs.get("header1", rs.getHeader1());
//header2 = prefs.get("header2", rs.getHeader2());
} catch (BackingStoreException ex) {
System.err.println(ex);
}
header1= "Header 1";
header2= "Header 2";
cos.beginText();
cos.moveTextPositionByAmount(220, 810);
cos.setFont(headerFont, header1FontSize);
cos.drawString(header1);
cos.endText();
cos.beginText();
cos.moveTextPositionByAmount(220, 800);
cos.setFont(headerFont, header2FontSize);
cos.drawString(header2);
cos.endText();
cos.beginText();
cos.moveTextPositionByAmount(220, 790);
cos.setFont(headerFont, headerFontSize);
cos.drawString("Report: Filtered Audit Report");
cos.endText();
//cos.beginText();
// cos.moveTo(200, 30);
//cos.setFont(headerFont, headerFontSize);
// cos.drawString(header2);
//cos.endText();
/* Initialize DataTable */
float margin = 20;
float tableWidth = page.getMediaBox().getWidth() - (2 * margin);
float yStartNewPage = page.getMediaBox().getHeight() - (2 * margin);
float yStart = yStartNewPage;
float bottomMargin = -800;
BaseTable table = new BaseTable(yStart, yStartNewPage,
bottomMargin, tableWidth, margin, doc, page, true, true);
Row<PDPage> dataRow = table.createRow(dataCellHeight);
for (int i = 0; i < data.size() - 1; i++) {
System.out.println(data.get(i));
}
drawTableData(table, dataCellHeight, 20, data, 1,doc,page);
table.draw();
File result;
if (Objects.isNull(destPath)) {
cos.close();
result = new File("temp.pdf");
} else {
result = new File(destPath);
}
System.out.println("befor save result");
doc.save(result);
System.out.println("after save result");
}
public void drawTableData(BaseTable table, float dataCellHeight, float
cellWidth, List<Audit> data, int style,PDDocument doc,PDPage page) {
String s;
Cell<PDPage> cell;
// for (int k = 0; k < data.size(); k++) {
System.out.println("inside drawtable for ");
for (int i = 0; i < data.size(); i++) { // add row
System.out.println("inside drawtable for " + i);
Audit atmp = data.get(i);
//if (i==35) {
// doc.addPage(page);
//}
Row<PDPage> sTableRow = table.createRow(dataCellHeight);
for (int j = 0; j <= 2; j++) { //add cell in the rows
if (j == 0) { // normal cells on right
s = atmp.getTimeStamp();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
setStyle(style, cell);
//k++;
} else if (j == 1) { //big cells on left
s = atmp.getDiscription();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth + 50, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
setStyle(style, cell);
// k++;
} else if (j == 2) { //top blank cell
//System.out.println("In j null and 0 " + j);
s = atmp.getUserID();
s = s.replaceAll("^\"|\"$", "");
cell = sTableRow.createCell(cellWidth - 10, s, HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
//cell.setBottomBorderStyle(null);
setStyle(style, cell);
//k++;
}
}
table.addHeaderRow(sTableRow);
System.out.println(" row added ");
}
//}
}
public void setStyle(int type, Cell cell) {
// type : 0 as header, 1 as table body
if (type == 0) {
cell.setFont(headerFont);
//cell.setHeight(headerCellHeight);
cell.setFontSize(headerFontSize);
cell.setBottomPadding(3);
} else if (type == 1) {
cell.setTopPadding(1);
cell.setFont(font);
cell.setAlign(HorizontalAlignment.LEFT);
//cell.setHeight(dataCellHeight);
cell.setFontSize(fontSize);
cell.setBottomPadding(1);
}
}
I found a silly problem in my code. I am telling this so that someone else must not repeat this.
I treated every row of the data table as header row. So it went to new page.
To be specific. In the function drawTableData I removed table.addHeaderRow(sTableRow)

PDFBOX: Indexing using pdfbox

I am in requirement of creating an index for PDF document & based on the index i want to display the page.
problem is page number are created dynamically so static page number cannot be used, can anyone suggest me links or examples
here is my code and it works for me to redirect into different pages while clicking in the page number on index page
public class LinkPdf {
static final float INCH = 72;
public static List<PDAnnotation> annotations;
#SuppressWarnings("null")
public static void main(String[] args) throws Exception {
PDRectangle position = null;
PDDocument document = new PDDocument();
try {
for (int i = 0; i < 10; i++) {
PDPage page = new PDPage();
document.addPage(page);
}
PDPage page1 = document.getPage(0);
HashMap<Integer, String> pgs = new HashMap<Integer, String>();
for (int i = 0; i < document.getNumberOfPages(); i++) {
pgs.put(i, "Jump to Page" + i);
}
PDFont font = PDType1Font.HELVETICA_BOLD;
PDPageContentStream contents = new PDPageContentStream(document,
page1);
contents.beginText();
contents.setFont(font, 18);
contents.newLineAtOffset(50, 600);
contents.setLeading(20f);
contents.showText("PDFBox");
position = new PDRectangle();
for (int i = 0; i < document.getNumberOfPages(); i++) {
contents.newLine();
contents.showText(pgs.get(i));
contents.newLine();
}
contents.endText();
contents.close();
PDRectangle[] pos1 = new PDRectangle[document.getNumberOfPages()];
for(int i=0;i<document.getNumberOfPages();i++){
pos1[i]=new PDRectangle();
pos1[i].setLowerLeftX(50);
pos1[i].setLowerLeftY(575-(i*40));
pos1[i].setUpperRightX(INCH + 100);
pos1[i].setUpperRightY(585-(i*40));
getPage(document, page1, pgs.get(i), i, pos1[i]);
}
document.save("D:/link.pdf");
System.out.println("Completed");
} finally {
document.close();
}
}
public static void getPage(PDDocument document, PDPage page1, String txt,
int pageno, PDRectangle position) throws IOException {
annotations = page1.getAnnotations();
PDBorderStyleDictionary borderThick = new PDBorderStyleDictionary();
borderThick.setWidth(INCH / 12); // 12th inch
PDBorderStyleDictionary borderThin = new PDBorderStyleDictionary();
borderThin.setWidth(INCH / 72); // 1 point
PDBorderStyleDictionary borderULine = new PDBorderStyleDictionary();
borderULine.setStyle(PDBorderStyleDictionary.STYLE_UNDERLINE);
borderULine.setWidth(INCH / 72); // 1 point
float pw = page1.getMediaBox().getUpperRightX();
float ph = page1.getMediaBox().getUpperRightY();
float textWidth = PDType1Font.TIMES_BOLD.getStringWidth("PDFBox") / 1000 * 18;
PDAnnotationLink pageLink = new PDAnnotationLink();
pageLink.setBorderStyle(borderULine);
textWidth = PDType1Font.TIMES_BOLD.getStringWidth(txt) / 1000 * 18;
pageLink.setRectangle(position);
PDActionGoTo actionGoto = new PDActionGoTo();
PDPageDestination dest = new PDPageFitWidthDestination();
dest.setPage(document.getPage(pageno));
actionGoto.setDestination(dest);
pageLink.setAction(actionGoto);
annotations.add(pageLink);
}
}

Add padding to table cells using iTextPdf

Following is a demo code to generate a PDF doc from a HTML source:
public class SimpleAdhocReport
{
public SimpleAdhocReport()
{
build();
}
private void build()
{
AdhocConfiguration configuration = new AdhocConfiguration();
AdhocReport report = new AdhocReport();
configuration.setReport(report);
AdhocColumn column = new AdhocColumn();
column.setName("item");
report.addColumn(column);
column = new AdhocColumn();
column.setName("orderdate");
report.addColumn(column);
column = new AdhocColumn();
column.setName("quantity");
report.addColumn(column);
column = new AdhocColumn();
column.setName("unitprice");
report.addColumn(column);
try
{
AdhocManager.saveConfiguration(configuration, new FileOutputStream("d:/configuration.xml"));
#SuppressWarnings("unused")
AdhocConfiguration loadedConfiguration = AdhocManager.loadConfiguration(new FileInputStream("d:/configuration.xml"));
JasperReportBuilder reportBuilder = AdhocManager.createReport(configuration.getReport());
reportBuilder.setDataSource(createDataSource());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
reportBuilder.toHtml(baos);
String html = new String(baos.toByteArray(), "UTF-8");
baos.close();
Whitelist wl = Whitelist.simpleText();
wl.addTags("table", "tr", "td");
String clean = Jsoup.clean(html, wl);
clean = clean.replace("<td></td>", "");
clean = clean.replace("<td> </td>", "");
clean = clean.replace("<td> ", "<td>");
Document doc = Jsoup.parse(clean);
for (Element element : doc.select("*"))
{
if (!element.hasText() && element.isBlock())
{
element.remove();
}
}
clean = doc.body().html();
int startIndex = clean.indexOf("<table>", 6);
int endIndex = clean.indexOf("</table>");
clean = clean.substring(startIndex, endIndex + 8);
BufferedWriter writer = new BufferedWriter(new FileWriter(("d:/test.html")));
writer.write(clean);
writer.close();
try
{
createPdf(clean);
}
catch (DocumentException e)
{
e.printStackTrace();
}
}
catch (DRException e)
{
e.printStackTrace();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private JRDataSource createDataSource()
{
DRDataSource dataSource = new DRDataSource("item", "orderdate", "quantity", "unitprice");
for (int i = 0; i < 20; i++)
{
dataSource.add("Book", new Date(), (int) (Math.random() * 10) + 1,
new BigDecimal(Math.random() * 100 + 1).setScale(4, BigDecimal.ROUND_HALF_UP));
}
return dataSource;
}
public static void main(String[] args)
{
new SimpleAdhocReport();
}
public void createPdf(String html) throws IOException, DocumentException
{
com.itextpdf.text.Document document = new com.itextpdf.text.Document(PageSize.LETTER);
document.setMargins(30, 30, 80, 30);
PdfWriter.getInstance(document, new FileOutputStream("D:\\HTMLtoPDF.pdf"));
document.open();
PdfPTable table = null;
ElementList list = com.itextpdf.tool.xml.XMLWorkerHelper.parseToElementList(html, null);
for (com.itextpdf.text.Element element : list)
{
table = new PdfPTable((PdfPTable) element);
}
table.setWidthPercentage(100);
ArrayList<PdfPRow> rows = table.getRows();
for (PdfPRow rw : rows)
{
PdfPCell[] cells = rw.getCells();
for (PdfPCell cl : cells)
{
cl.setVerticalAlignment(com.itextpdf.text.Element.ALIGN_MIDDLE);
cl.setBorder(PdfPCell.NO_BORDER);
cl.setNoWrap(true);
cl.setPadding(10f);
cl.setCellEvent(new MyCell());
}
}
document.add(table);
document.close();
}
}
class MyCell implements PdfPCellEvent
{
public void cellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases)
{
float x1 = position.getLeft() - 2;
float x2 = position.getRight() + 2;
float y1 = position.getTop() + 2;
float y2 = position.getBottom() - 2;
PdfContentByte canvas = canvases[PdfPTable.LINECANVAS];
canvas.rectangle(x1, y1, x2 - x1, y2 - y1);
canvas.stroke();
}
}
I am working with jasper reports to create a adhoc report and generate the HTML from there. I have to generate a PDF from this HTML.
Couple of issue I am facing, any help is appreciated:
I am setting the
table.setWidthPercentage(100);
for a page with table its not working.
I have to increase spacing between columns. Tried what Bruno suggested here. Its not working. I have also tried using a solution from here with no luck. Ref. image below.
Also if i cell event to default is not working.
e.g.
table.getDefaultCell().setCellEvent()
Any suggestions ?
Update:
My Output
I was able to get the padding as i want by parsing the HTML following way:
public PdfPTable getTable(String cleanHTML) throws IOException
{
String CSS = "tr { text-align: center; } td { padding: 5px; }";
CSSResolver cssResolver = new StyleAttrCSSResolver();
CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream(CSS.getBytes()));
cssResolver.addCss(cssFile);
// HTML
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
// Pipelines
ElementList elements = new ElementList();
ElementHandlerPipeline pdf = new ElementHandlerPipeline(elements, null);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
// XML Worker
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.parse(new ByteArrayInputStream(cleanHTML.getBytes()));
return (PdfPTable) elements.get(0);
}
That fixes the issue mentioned in question 2. Q3 is not longer required.

PDFBox: put two A4 pages on one A3

I have a pdf document with one or more pages A4 paper.
The resulting pdf document should be A3 paper where each page contains two from the first one (odd on the left, even on the right side).
I already got it to render the A4 pages into images and the odd pages are successfully placed on the first parts of a new A3 pages but I cannot get the even pages to be placed.
public class CreateLandscapePDF {
public void renderPDF(File inputFile, String output) {
PDDocument docIn = null;
PDDocument docOut = null;
float width = 0;
float height = 0;
float posX = 0;
float posY = 0;
try {
docIn = PDDocument.load(inputFile);
PDFRenderer pdfRenderer = new PDFRenderer(docIn);
docOut = new PDDocument();
int pageCounter = 0;
for(PDPage pageIn : docIn.getPages()) {
pageIn.setRotation(270);
BufferedImage bufferedImage = pdfRenderer.renderImage(pageCounter);
width = bufferedImage.getHeight();
height = bufferedImage.getWidth();
PDPage pageOut = new PDPage(PDRectangle.A3);
PDImageXObject image = LosslessFactory.createFromImage(docOut, bufferedImage);
PDPageContentStream contentStream = new PDPageContentStream(docOut, pageOut, AppendMode.APPEND, true, true);
if((pageCounter & 1) == 0) {
pageOut.setRotation(90);
docOut.addPage(pageOut);
posX = 0;
posY = 0;
} else {
posX = 0;
posY = width;
}
contentStream.drawImage(image, posX, posY);
contentStream.close();
bufferedImage.flush();
pageCounter++;
}
docOut.save(output + "\\LandscapeTest.pdf");
docOut.close();
docIn.close();
} catch(IOException io) {
io.printStackTrace();
}
}
}
I'm using Apache PDFBox 2.0.2 (pdfbox-app-2.0.2.jar)
Thank you very much for your help and the link to the other question - I think I already read it but wasn't able to use in in my code yet.
But finally the PDFClown made the job, though I think it's not very nice to use PDFBox and PDFClown in the same program.
Anyway here's my working code to combine A4 pages on A3 paper.
public class CombinePages {
public void run(String input, String output) {
try {
Document source = new File(input).getDocument();
Pages sourcePages = source.getPages();
Document target = new File().getDocument();
Page targetPage = null;
int pageCounter = 0;
double moveByX = .0;
for(Page sourcePage : source.getPages()) {
if((pageCounter & 1) == 0) {
//even page gets a blank page
targetPage = new Page(target);
target.setPageSize(PageFormat.getSize(PageFormat.SizeEnum.A3, PageFormat.OrientationEnum.Landscape));
target.getPages().add(targetPage);
moveByX = .0;
} else {
moveByX = .50;
}
//get content from source page
XObject xObject = sourcePages.get(pageCounter).toXObject(target);
PrimitiveComposer composer = new PrimitiveComposer(targetPage);
Dimension2D targetSize = targetPage.getSize();
Dimension2D sourceSize = xObject.getSize();
composer.showXObject(xObject, new Point2D.Double(targetSize.getWidth() * moveByX, targetSize.getHeight() * .0), new Dimension(sourceSize.getWidth(), sourceSize.getHeight()), XAlignmentEnum.Left, YAlignmentEnum.Top, 0);
composer.flush();
pageCounter++;
}
target.getFile().save(output + "\\CombinePages.pdf", SerializationModeEnum.Standard);
source.getFile().close();
} catch (FileNotFoundException fnf) {
log.error(fnf);
} catch (IOException io) {
log.error(io);
}
}
}

How to read bookmarks in PDF using itext at multi level?

I am using iText-Java to split PDFs at bookmark level.
Does anybody know or have any examples for splitting a PDF at bookmarks that exist at a level 2 or 3?
For ex: I have the bookmarks in the following levels:
Father
|-Son
|-Son
|-Daughter
|-|-Grand son
|-|-Grand daughter
Right now I have below code to read the bookmark which reads the base bookmark(Father). Basically SimpleBookmark.getBookmark(reader) line did all the work.
But I want to read the level 2 and level 3 bookmarks to split the content present between those inner level bookmarks.
public static void splitPDFByBookmarks(String pdf, String outputFolder){
try
{
PdfReader reader = new PdfReader(pdf);
//List of bookmarks: each bookmark is a map with values for title, page, etc
List<HashMap> bookmarks = SimpleBookmark.getBookmark(reader);
for(int i=0; i<bookmarks.size(); i++){
HashMap bm = bookmarks.get(i);
HashMap nextBM = i==bookmarks.size()-1 ? null : bookmarks.get(i+1);
//In my case I needed to split the title string
String title = ((String)bm.get("Title")).split(" ")[2];
log.debug("Titel: " + title);
String startPage = ((String)bm.get("Page")).split(" ")[0];
String startPageNextBM = nextBM==null ? "" + (reader.getNumberOfPages() + 1) : ((String)nextBM.get("Page")).split(" ")[0];
log.debug("Page: " + startPage);
log.debug("------------------");
extractBookmarkToPDF(reader, Integer.valueOf(startPage), Integer.valueOf(startPageNextBM), title + ".pdf",outputFolder);
}
}
catch (IOException e)
{
log.error(e.getMessage());
}
}
private static void extractBookmarkToPDF(PdfReader reader, int pageFrom, int pageTo, String outputName, String outputFolder){
Document document = new Document();
OutputStream os = null;
try{
os = new FileOutputStream(outputFolder + outputName);
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, os);
document.open();
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF data
PdfImportedPage page;
while(pageFrom < pageTo) {
document.newPage();
page = writer.getImportedPage(reader, pageFrom);
cb.addTemplate(page, 0, 0);
pageFrom++;
}
os.flush();
document.close();
os.close();
}catch(Exception ex){
log.error(ex.getMessage());
}finally {
if (document.isOpen())
document.close();
try {
if (os != null)
os.close();
} catch (IOException ioe) {
log.error(ioe.getMessage());
}
}
}
Your help is much appreciated.
Thanks in advance! :)
You get an ArrayList<HashMap> when you call SimpleBookmark.getBookmark(reader); (do the cast if you need it). Try to iterate through that Arraylist and see its structure. If a bookmarks have sons (as you call it), it will contains another list with the same structure.
A recursive method could be the solution.
Reference for those who are looking at this using itext7
public void walkOutlines(PdfOutline outline, Map<String, PdfObject> names, PdfDocument pdfDocument,List<String>titles,List<Integer>pageNum) { //----------loop traversing all paths
for (PdfOutline child : outline.getAllChildren()){
if(child.getDestination() != null) {
prepareIndexFile(child,names,pdfDocument,titles,pageNum,list);
}
}
}
//-----Getting pageNumbers from outlines
public void prepareIndexFile(PdfOutline outline, Map<String, PdfObject> names, PdfDocument pdfDocument,List<String>titles,List<Integer>pageNum) {
String title = outline.getTitle();
PdfDestination pdfDestination = outline.getDestination();
String pdfStr = ((PdfString)pdfDestination.getPdfObject()).toUnicodeString();
PdfArray array = (PdfArray) names.get(pdfStr);
PdfObject pdfObj = array != null ? array.get(0) : null;
Integer pageNumber = pdfDocument.getPageNumber((PdfDictionary)pdfObj);
titles.add(title);
pageNum.add(pageNumber);
if(outline.getAllChildren().size() > 0) {
for (PdfOutline child : outline.getAllChildren()){
prepareIndexFile(child,names,pdfDocument,titles,pageNum);
}
}
}
public boolean splitPdf(String inputFile, final String outputFolder) {
boolean splitSuccess = true;
PdfDocument pdfDoc = null;
try {
PdfReader pdfReaderNew = new PdfReader(inputFile);
pdfDoc = new PdfDocument(pdfReaderNew);
final List<String> titles = new ArrayList<String>();
List<Integer> pageNum = new ArrayList<Integer>();
PdfNameTree destsTree = pdfDoc.getCatalog().getNameTree(PdfName.Dests);
Map<String, PdfObject> names = destsTree.getNames();//--------------------------------------Core logic for getting names
PdfOutline root = pdfDoc.getOutlines(false);//--------------------------------------Core logic for getting outlines
walkOutlines(root,names, pdfDoc, titles, pageNum,content); //------Logic to get bookmarks and pageNumbers
if (titles == null || titles.size()==0) {
splitSuccess = false;
}else { //------Proceed if it has bookmarks
for(int i=0;i<titles.size();i++) {
String title = titles.get(i);
String startPageNmStr =""+pageNum.get(i);
int startPage = Integer.parseInt(startPageNmStr);
int endPage = startPage;
if(i == titles.size() - 1) {
endPage = pdfDoc.getNumberOfPages();
}else {
int nextPage = pageNum.get(i+1);
if(nextPage > startPage) {
endPage = nextPage - 1;
}else {
endPage = nextPage;
}
}
String outFileName = outputFolder + File.separator + getFileName(title) + ".pdf";
PdfWriter pdfWriter = new PdfWriter(outFileName);
PdfDocument newDocument = new PdfDocument(pdfWriter, new DocumentProperties().setEventCountingMetaInfo(null));
pdfDoc.copyPagesTo(startPage, endPage, newDocument);
newDocument.close();
pdfWriter.close();
}
}
}catch(Exception e){
//---log
}
}

Categories