Dynamically positioning the table and bar chart generated using jfree chart - itext

Hi All Iam using itextpdf-5.1.0.jar, displaying Table(the values in this table are fetched from the database based on start date and end date in the input screen) and bar chart for the values in the above table.
The problem is I want to position the bar chart below the table, values that iam fetching from the database may vary depending upon start date and end date, now Iam positioning table and bar chart by giving some static values(234,567) , if there are large no of values table values and bar chart are getting overrided. Is there any other way to position table and bar chart dynamically.
Document document = new Document(PageSize.A4_LANDSCAPE, 10, 10, 10, 10);
document.open();
document.add(new Paragraph("Batch Report:", FontFactory.getFont(FontFactory.COURIER, 10, Font.BOLD, new CMYKColor(255, 255, 255, 255))));
Paragraph paragraph1 = new Paragraph();
paragraph1.setSpacingBefore(4);
document.add(paragraph1);
PdfPTable table = new PdfPTable(5);
table.setWidthPercentage(100);
PdfPCell c1;
for (BoardBean bean : listHeader) {
addColumn(bean.getID(),c1,table,myColor,btableheadercolor);
}
Add Column values to table
private void addColumn(String text,PdfPCell c1,PdfPTable dataTable,BaseColor myColor,BaseColor btablecolumncolor) {
try {
final Font tabletdcolor = new Font(Font.FontFamily.HELVETICA, 6, Font.NORMAL, BaseColor.BLACK);
c1 = new PdfPCell(new Paragraph(text, tabletdcolor));
cellStyle(c1, myColor, btablecolumncolor);
dataTable.addCell(c1);
} catch (Exception ex) {
ex.printStackTrace();
}
}
Generating bar chart
JFreeChart reportBarChart = genBatchReportBarChart(listHeader);
PdfTemplate reportTemplate = contentByte.createTemplate(280, 230);
Graphics2D reportGraphics = reportTemplate.createGraphics(280, 230, new DefaultFontMapper());
Rectangle2D reportRectangle = new Rectangle2D.Double(0, 0, 280, 230);
reportBarChart.draw(reportGraphics, reportRectangle);
reportGraphics.dispose();
contentByte.addTemplate(reportTemplate, 10, height+150);
Now in the above code iam fixing the position of bar chart and if the values are low in number its good but if they are large in number bar chart is overriding the table values.Depending upon the table values the bar chart need to be aligned how can I achieve that.

You can ask the table for its total height after you've added the table to the document, and use that table height to decide where to put the chart.
Or (even easier to achieve): you can wrap the PdfTemplate inside an Image object:
Image img = Image.getInstance(reportTemplate);
Add that image with document.add() right after you've added the table (assuming that you're adding the table with document.add()).

Related

Table NoWrap Option in iText 7?

I'm converting iText5 code to iText7. One of the properties we use is NoWrap (= true) on some of our cells. What is the iText 7 equivolent? Thanks!
new PdfPCell { NoWrap = true, ... }
You can use Property.OVERFLOW_X to control the overflow strategy of the content. But it needs to be set on the elements that contain the content, normally on a paragraph.
Here is an example of a code adding a table with a cell that contains content which does not fit in the given cell width (100pt):
PdfDocument pdfDocument = new PdfDocument(new PdfWriter(outFileName));
Document document = new Document(pdfDocument);
Table table = new Table(new float[] {100, 100, 100});
table.setFixedLayout();
table.setWidth(300);
table.addCell("Hello world");
Paragraph p = new Paragraph("ThisIsAVeryLongLongWordWhichOverflowsCellWidth").setFontColor(ColorConstants.GREEN);
table.addCell(p);
p.setProperty(Property.OVERFLOW_X, OverflowPropertyValue.VISIBLE);
table.addCell("Last cell");
document.add(table);
document.close();

How can I take text and convert to PDF with landscape orientation and two text columns?

I need to change the paper orientation, and then divide the text into two columns. I want like it:
I come from a large text file and I need to add all of this text in the PDF as in the photo.
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(DEST));
PageSize ps = PageSize.A4;;
Document doc = new Document(pdfDoc, ps);
BufferedReader br = new BufferedReader(new FileReader("verybigfileWithText.txt"));
while ((line = br.readLine()) != null) {
//split pdf and add text in two column without overlapping page
}
doc.close();
And I need to be able to change margin in center(between two columns) and margin top/right/bot/left. And get width every columns :)
Help me please
Pdf:
https://dropmefiles.com/HqD6f
To change the orientation of the page you can use PageSize#rotate, e.g. PageSize.A4.rotate()
To put content into two (or more) columns, you can create your own document renderer, or use an existing ColumnDocumentRenderer which suits your needs. It accepts column areas which allows you to control margins (or even position columns in a peculiar way which is probably not your use case):
Document document = new Document(pdfDocument, PageSize.A4.rotate());
Rectangle[] columnAreas = new Rectangle[] {new Rectangle(30, 30, 350, 520), new Rectangle(430, 30, 350, 520)};
ColumnDocumentRenderer renderer = new ColumnDocumentRenderer(document, columnAreas);
document.setRenderer(renderer);
document.add(new Paragraph(text).setTextAlignment(TextAlignment.JUSTIFIED));
document.close();
The result looks like this:

Header with 2 cells aligned in the same row, itextpdf 5.5.10

I have a row in my header, which looks good, but I need to add another String in the same row, so it is on the right side of it
When I try to add that String in the same cell, everything loses the alignment
private void addHeader(PdfWriter writer) {
PdfPTable tableHeader = new PdfPTable(2);
try {
// set defaults
header.setWidths(new int[] { 20, 12, 12 });
header.setTotalWidth(527);
header.setLockedWidth(true);
header.getDefaultCell().setFixedHeight(5);
header.getDefaultCell().setBorder(Rectangle.BOTTOM);
header.getDefaultCell().setBorderColor(BaseColor.LIGHT_GRAY);
// add text
PdfPCell text = new PdfPCell();
text.setPaddingBottom(12);
text.setPaddingLeft(8);
text.setBorder(Rectangle.BOTTOM);
text.setBorderColor(BaseColor.LIGHT_GRAY);
text.addElement(new Phrase("Hi", new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD)));
text.addElement(new Phrase("", new Font(Font.FontFamily.HELVETICA, 8)));
text.addElement(new Phrase("Hi" + "CVE-2017-2018", new Font(Font.FontFamily.HELVETICA, 9)));
header.addCell(text);
// add image
Image logo = Image.getInstance(App.class.getResource(LOGO_2));
header.addCell(logo);
PdfPCell cveTitle = new PdfPCell();
cveTitle.setPaddingBottom(15);
cveTitle.setPaddingLeft(8);
cveTitle.setBorder(Rectangle.BOTTOM);
cveTitle.setBorderColor(BaseColor.LIGHT_GRAY);
cveTitle.addElement(new Phrase("3 Cell", new Font(Font.FontFamily.HELVETICA, 16, Font.BOLD)));
header.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
header.addCell(cveTitle);
}
CVE-2010-2016
Is just what I want to do, leave it on the right side
Update
The solution was to add a new value to the array, corresponding to a new cell, and also instantiating PdfPCell again, thks
Just from the classname PdfPTable, I can tell the iText version you are using is pretty outdated.
Please consider switching to a newer version. Latest version is iText7.
I think what you're looking for is colspan and rowspan.
Have a look at the tutorial:
http://developers.itextpdf.com/examples/tables/clone-colspan-and-rowspan

positioning text using itextSharp in C3

I am trying to generate a pdf on button click. I am having challenge to design the page. If anybody can help on, how to position the text in particular position.
Say I want my address to in the top right corner and heading in the center.
Here is the code I am working on:
private void pdf_btn_Click(object sender, EventArgs e)
{
SaveFileDialog svg = new SaveFileDialog();
svg.ShowDialog();
using (FileStream stream = new FileStream(svg.FileName + ".pdf", FileMode.Create))
{
// Create a Document object
var document = new Document(PageSize.A4, 50, 50, 25, 25);
// Create a new PdfWrite object, writing the output to a MemoryStream
// var output = new MemoryStream();
var writer = PdfWriter.GetInstance(document, stream);
document.Open();
// First, create our fonts... (For more on working w/fonts in iTextSharp, see: http://www.mikesdotnetting.com/Article/81/iTextSharp-Working-with-Fonts
var titleFont = FontFactory.GetFont("Arial", 18, Convert.ToInt32(Font.Bold));
var AddressFont = FontFactory.GetFont("Arial", 7, Convert.ToInt32(Font.Bold));
var boldTableFont = FontFactory.GetFont("Arial", 12, Convert.ToInt32(Font.Bold));
var endingMessageFont = FontFactory.GetFont("Arial", 10, Convert.ToInt32(Font.Italic));
var bodyFont = FontFactory.GetFont("Arial", 12);
// Add the "" title
document.Add(new Paragraph("Certificate of Analysis", titleFont));
// Add Address
var text = document.Add(new Paragraph("Abc Company", AddressFont));
document.Add(new Paragraph("Tel:(xx) xxx-xxxx, (xxx) xxx-xxx", AddressFont));
document.Add(new Paragraph("Fax: (xxx) xxx-xxx, , AddressFont));
document.Close();
stream.Close();
}
}
There are different ways to achieve what you want.
Currently, you are telling iText to do the layout. If you want to center the text "Certificate of Analysis", then you could change the alignment of the Paragraph like this:
Paragraph header = new Paragraph("Certificate of Analysis", titleFont);
header.Alignment = Element.ALIGN_CENTER;
document.Add(header);
If you want the text "Abc Company" to be right-aligned, you can change he alignment like this:
Paragraph company = new Paragraph("Abc Company", AddressFont);
company.Alignment = Element.ALIGN_RIGHT;
document.Add(company);
Of course: when we add company, it will start on a new line under header. Maybe you want the text to be on the same line.
In that case, why not use a PdfPTable?
PdfPTable myTable = new PdfPTable(3);
myTable.WidthPercentage = 100;
PdfPCell mydate = new PdfPCell(new Phrase("April 22, 2015", myfont));
mydate.Border = Rectangle.NO_BORDER;
myTable.AddCell(mydate);
PdfPCell header = new PdfPCell(new Phrase("Certificate of Analysis", titleFont));
header.Border = Rectangle.NO_BORDER;
header.HorizontalAlignment = Element.ALIGN_CENTER;
myTable.AddCell(header);
PdfPCell address = new PdfPCell(new Phrase("Company Address", AddressFont));
address.Border = Rectangle.NO_BORDER;
address.HorizontalAlignment = Element.ALIGN_RIGHT;
myTable.AddCell(address);
doc.Add(myTable);
Now the available width of your page will be divided in three, the date will be aligned to the left, the header will be centered, and the address will be aligned to the right. Obviously, you can add more data to a PdfPCell and more rows to the PdfPTable. This is just a simple proof of concept.
Another option, is to add the text at an absolute position (using coordinates). This can be done by using the ColumnText object. There are plenty of examples on this in The Best iText Questions on StackOverflow

Table shows extra blank columns at the end

I am using jface tableViewer.When table has no data in it ,it shows all columns correctly But when Data gets added to the table it shows extra blank space or column at the end of the table.
I am using TreeViewer + TreeViewerColumn and had this problem too, this workaround might work for your TableViewer too: Programmatically set the size of the last column on parent resize:
treeViewer.getTree().addControlListener(new ControlAdapter() {
public void controlResized(ControlEvent e) {
packAndFillLastColumn();
}
});
where the action is in
// Resize last column in tree viewer so that it fills the client area completely if extra space.
protected void packAndFillLastColumn() {
Tree tree = treeViewer.getTree();
int columnsWidth = 0;
for (int i = 0; i < tree.getColumnCount() - 1; i++) {
columnsWidth += tree.getColumn(i).getWidth();
}
TreeColumn lastColumn = tree.getColumn(tree.getColumnCount() - 1);
lastColumn.pack();
Rectangle area = tree.getClientArea();
Point preferredSize = tree.computeSize(SWT.DEFAULT, SWT.DEFAULT);
int width = area.width - 2*tree.getBorderWidth();
if (preferredSize.y > area.height + tree.getHeaderHeight()) {
// Subtract the scrollbar width from the total column width
// if a vertical scrollbar will be required
Point vBarSize = tree.getVerticalBar().getSize();
width -= vBarSize.x;
}
// last column is packed, so that is the minimum. If more space is available, add it.
if(lastColumn.getWidth() < width - columnsWidth) {
lastColumn.setWidth(width - columnsWidth);
}
}
Works well for me - you might want to set column resizable to false ;-). This can also be called when data in the last column changes (introducting / removing vertical scroll bar).
Thanks Thomas. Your idea worked for me as well, though I was using TableViewer and TableColumn.
Quoting my code so that others can take some hints.
`public void controlResized(ControlEvent e) {
if ( listOfTableColumns.size() != colProportions.length )
{
logger.warn( "Number of columns passed and size of column proportions array are different. " +
"Columns resizing shall not be effective on GUI window resizing" );
return;
}
Rectangle area = tableBaseComposite.getClientArea();
Point size = theTable.computeSize(SWT.DEFAULT, SWT.DEFAULT);
ScrollBar vBar = theTable.getVerticalBar();
int width = area.width - theTable.computeTrim(0,0,0,0).width - vBar.getSize().x;
if (size.y > area.height + theTable.getHeaderHeight()) {
// Subtract the scrollbar width from the total column width
// if a vertical scrollbar will be required
Point vBarSize = vBar.getSize();
width -= vBarSize.x;
}
Point oldSize = theTable.getSize();
if (oldSize.x > area.width) {
// table is getting smaller so make the columns
// smaller first and then resize the table to
// match the client area width
int index = 0 ;
for ( Iterator<TableColumn> iterator = listOfTableColumns.iterator(); iterator.hasNext(); )
{
TableColumn column = iterator.next();
column.setWidth( (int) numberFromPercentage( width, colProportions[index++] ) );
}
listOfTableColumns.get( listOfTableColumns.size() - 1).pack();
theTable.setSize(area.width, area.height);
} else {
// table is getting bigger so make the table
// bigger first and then make the columns wider
// to match the client area width
int index = 0;
theTable.setSize(area.width, area.height);
for ( Iterator<TableColumn> iterator = listOfTableColumns.iterator(); iterator.hasNext(); )
{
TableColumn column = iterator.next();
column.setWidth( (int) numberFromPercentage( width, colProportions[index++] ) );
}
listOfTableColumns.get( listOfTableColumns.size() - 1).pack();
}
}`
No need for complicated hacks to remove the extra unwanted column space at the end...
Just create a columnLayout:
TableColumnLayout columnLayout = new TableColumnLayout();
and then set it to each of your columns:
columnLayout.setColumnData(YOUR_VIEWER_COLUMN1.getColumn(), new ColumnPixelData(200));
columnLayout.setColumnData(YOUR_VIEWER_COLUMN2.getColumn(), new ColumnWeightData(200, 100));
Finally, set the layout on your parent composite:
parent.setLayout(columnLayout);
Full sample:
public void createPartControl(Composite parent) {
TableViewer viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
TableViewerColumn keyColumn = new TableViewerColumn(viewer, SWT.LEFT);
TableViewerColumn valueColumn = new TableViewerColumn(viewer, SWT.LEFT);
TableColumnLayout columnLayout = new TableColumnLayout();
columnLayout.setColumnData(keyColumn.getColumn(), new ColumnPixelData(200));
columnLayout.setColumnData(valueColumn.getColumn(), new ColumnWeightData(200, 100));
parent.setLayout(columnLayout);
}
Just guessing: maybe your columns do not get resized to fill all the table?
How do you set the widths of columns?
Consider using TableColumnLayout for the table container.
On windows, you will always get an extra column/row if the net width of all the columns that has been set up is less than the dimension of the table. So its always good to make your columns fit your table, also there is some space left for scroll bars, though I am not very sure about this, but its always better to specify whether you want vertical or horizontal scroll bars.
I used the packAndFillLastColumn() method and it worked for me. But I found one issue with it. My table was created with a border. After using the packAndFillLastColumn() method the border for the row no longer exists. I used the setLinesVisible(true) method within the packAndFillLastColumn() method but still that does not work.
So simple! Just remove this line in your table commands inside the createContents function:
table.getColumn(i).pack();
Good-luck
As a workaround use :
-For Column
use TableColumnLayout for the treeViewer's composite and set appropriate column data for each column using:
"tableColumnLayout.setColumnData(column,new ColumnWeightData(...as per your requirement));"
-For Row
Set GridData to the treeViewer's composite and provide height hint using
"gridData.heightHint = table.getItemHeight()*numberOfVisibleRows"
I found eclipse has marked it as WONTFIX.. so can not do much to remove this space..We have tp live with it...:)
To the end column we need to set the setWidth to window size or shell-size, parent-shell size like 1500,5000
final TableViewerColumn viewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
final TableColumn column = viewerColumn.getColumn();
column.setText(title);
column.setResizable(true);
column.setMoveable(true);
//set the setWidth size upto shell size or set upto to some size like 1000,1500,2000,5000
col.setWidth(comp.getShell().getSize().x); // or col.setWidth(1500) ;
return viewerColumn;