Add table row counts to every page - itext

How can I get the total number of rows written to a PdfPTable for every page using iTextSharp?
I want to put all of my code onStartPage
public class MyPdfPageEventHelpPageNo : iTextSharp.text.pdf.PdfPageEventHelper
{
public override void OnStartPage(PdfWriter writer, Document document)
{
/// my code
}
}

As Bruno said you'll want to look into IPdfPTableEvent. The downside of that specific interface is that it gets called on every page with only a copy of the table that's being printed to that specific page. So if you have a 200 row table, on page one you might only see a table with 50 rows and you never know the total row count. However, there's a more interesting interface that derives from it called IPdfPTableEventSplit which receives a copy of the original table, too, which is what you're looking for.
Below is a basic implementation of that interface. You might need to apply some additional logic to account for headers but it should be relatively easy. I'm also writing to the bottom of the page but you'll probably want to adjust that.
One very important note is that if a table doesn't split then the SplitTable is never called. I account for this in the TableLayout method by checking to see if our default row count of -1 has been changed to something else.
public class TableRowCounter : IPdfPTableEventSplit {
/// <summary>
/// Will hold the total number of rows in the table if a split occurs,
/// or negative one if no split happened.
/// </summary>
private int totalRowCount = -1;
/// <summary>
/// Holds the number of rows previously processed
/// </summary>
private int currentRowIndex = 0;
/// <summary>
/// Called if/when a table split happens
/// </summary>
/// <param name="table"></param>
public void SplitTable(PdfPTable table) {
this.totalRowCount = table.Rows.Count;
}
public void TableLayout(PdfPTable table, float[][] widths, float[] heights, int headerRows, int rowStart, PdfContentByte[] canvases) {
//Count the number of rows processed in this iteration
var thisRowCount = table.Rows.Count;
//Get one of the canvases to draw on. You could also use one of these
//PdfPTable.BACKGROUNDCANVAS or PdfPTable.LINECANVAS or PdfPTable.TEXTCANVAS
var writer = canvases[PdfPTable.BASECANVAS].PdfWriter;
//Create our text
var txt = String.Format(
"Showing rows {0} through {1} of {2} total rows",
(currentRowIndex + 1), //Zero-based index convert to one-based
(currentRowIndex + thisRowCount),
( -1 == totalRowCount ? thisRowCount : totalRowCount) //If a table split doesn't occur then our class variable won't be reset, just use the local count
);
//Draw our text
ColumnText.ShowTextAligned(writer.DirectContent, Element.ALIGN_LEFT, new Phrase(txt), 10, 10, 0);
//Increment our total row count
currentRowIndex += table.Rows.Count;
}
}
A very simple implementation of this code would be:
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
using (var fs = new FileStream(testFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
var t = new PdfPTable(1);
//Bind an instance of our table counter to the table event
t.TableEvent = new TableRowCounter();
for (var i = 1; i < 500; i++) {
t.AddCell(i.ToString());
}
doc.Add(t);
doc.Close();
}
}
}

Related

How do I increase the array and add a Gameobject to a new field?

I have a certain array that stores chunks of the world, and I need to increase the array through the script and place the chunk in a new field for the chunk. How can this be done?
I wrote this code:
public class WriteInWorld
{
[MenuItem("Assets/Add To World")]
public static void SetAsWmass()
{
GameObject[] selectedWmass = Selection.gameObjects;
Debug.Log(selectedWmass);
for (int i = 0; i < selectedWmass.Length; i++)
{
selectedWmass[i].GetComponent<Wmasss>().Chunk = selectedWmass[i];
Debug.Log(selectedWmass[i]);
}
//world = Find.FindWorldObjectAsBoolArgument(true);
//Debug.Log(world.GetComponent<World>().Chunk.ToList() + ": :" + world);
}
[MenuItem("Assets/Add To World", isValidateFunction:true)]
public static bool SetAsWmassValidator()
{
return Selection.activeObject is Wmasss;
}
}
Usually you have got 2 options:
If you know how many items you will need to store in a container, you can use an array.
If you don't know how many items you will need to store, a List might be what you're looking for.

Find all children with different tags -Unity

I'm trying to get a number of all children with a certain tag from the parent object.
For example if a parent object has 20 children and their tags can switch between two tags, I would want to find out how many have either tag.
I want to do it on a mouse click. I've tried using transform.childCount and FindGameObjectsWithTag() however I'm not having any luck.
Any suggestions or pointers?
public static class Extensions {
public static int ChildCountWithTag(this Transform tr, string tag, bool checkInactive = false) {
int count = 0;
Transform [] trs = tr.GetComponentsInChildren<Transform>(checkInactive);
foreach(Transform t in trs) {
if(t.gameObject.CompareTag(tag) == true) { count++; }
}
return count;
}
}
Then you call it as:
void Start() {
int result = this.transform.ChildCountWithTag("Tag");
int resultB = this.transform.ChildCountWithTag("OtherTag", true);
}
The first returns how many active with the given tag "Tag", the second how many children with the tag "OtherTag", including inactive ones.

PdfPageEventHelper in iTextSharp

sorry if this was posted earlier
I need to print list of expenses in a pdf document. the list may extend to any number of pages.
i'm writing the list by iterating the datarow object. One important thing is whenever the current page is going to end need to print the running total at the end of the page. i've wrote a class that implements PdfPageEventHandler as below
public class PaymentPageEventHandler : iTextSharp.text.pdf.PdfPageEventHelper
{
PdfContentByte cb;
private string subTotal = "";
public string GetSubtotal
{
set{
value = subTotal;
}
get
{
return subTotal;
}
}
public override void OnEndPage(PdfWriter writer, Document document)
{
// base.OnEndPage(writer, document);
cb = writer.DirectContent;
float[] iOuterTblWidth = { 10, 40F, 8, 12, 10 }; column widths of the table.
PdfPTable pdftbl = new PdfPTable(iOuterTblWidth);
PdfPCell cell = new PdfPCell();
cell.Colspan = 4;
cell.AddElement(new Chunk("Sub-Total"));
cell.HorizontalAlignment = 0;
pdftbl.AddCell(cell);
cell = new PdfPCell();
cell.AddElement(new Chunk(GetSubtotal));
cell.HorizontalAlignment = 2;
pdftbl.AddCell(cell);
}
}
the onEndPAge event above tries to write two columns. the above code gets called but the rows are not appearing in the pdf page.
I'm calling the above class like below
PaymentPageEventHandler ppem = new PaymentPageEventHandler();
ppem.GetSubtotal = "123"; // test value to print as running total
writer.PageEvent = ppem; // assigning event to writer object
Should i call explicity the PdfContentByte variable cb to write. if so how should i write the cells to the pdf.
can any one help me out on this.
You need to add the table using the WriteSelectedRows method. Please read the documentation and take a look at this example (or the C# ports of the examples)
Look for the line:
table.WriteSelectedRows(0, -1, 34, 803, writer.DirectContent);
Obviously, you'll need to adapt the coordinates.

Remove a row in a GWT Datagrid without scrolling to the top of the grid

I have a datagrid that may display many rows per page. Let's say I am displayed 25 rows per page. The viewable area of the grid, however, is only 10 rows. i.e. There is only 400px for the entire grid and each row is 40px. So there is a scroll bar on the grid.
When I remove a single row in the grid, the grid automatically moves to the first row in the grid. If I have scrolled the bottom and deleted the last row, I am once again moved to the 1st row.
I have attempted several ways of combatting this, but I can't find a solution that works the way I want it to.
I've tried scrolling the row directly before or after the deleted row into view using the scrollIntoView() method.
I've tried figuring out how to determine which rows were in the visible range before the deletion, but the getVisibleRange() method is relevant to the page range, not the actual displayed range.
I've searched the web for this and seems like I'm the only one having this problem. What am I missing?
I had the same issue, I found that the bug happend if dataGrid has
keyboardSelectionPolicy="BOUND_TO_SELECTION"
If you use ListDataProvider to manage the DataGrid's data, then the DataGrid will not scroll when removing/adding items.
Here is a minimal example of removing grid rows without any scrolling (all contained within the entry point class):
Class for DataGrid Rows:
private class Item{
public String text;
public int value;
public Item(String text, int value){
this.text = text;
this.value = value;
}
}
Filling the DataGrid:
Here I use a private variable, data, to hold the items for the DataGrid. Note, that we must attach the dataGrid to data via the addDataDisplay method.
ListDataProvider data;
public void onModuleLoad() {
// build grid:
DataGrid dataGrid = new DataGrid();
BuildColumns(dataGrid);
dataGrid.setWidth("300px");
dataGrid.setHeight("300px");
// add items:
data = new ListDataProvider();
for(int i = 1; i < 25; i++){
data.getList().add(new Item("Item " + i, i));
}
data.addDataDisplay(dataGrid);
// display:
RootPanel.get().add(dataGrid);
}
Building the DataGrid:
This private method is used to build the columns for the DataGrid. Inside of the FieldUpdater for delCol, which is used to listen for click events for button columns, we remove the respective item from data, and call data.refresh() to update the DataGrid display.
private void BuildColumns(DataGrid dataGrid){
Column textCol = new Column(new SafeHtmlCell()) {
#Override
public SafeHtml getValue(Item object) {
SafeHtmlBuilder sb = new SafeHtmlBuilder();
sb.appendEscaped(object.text);
return sb.toSafeHtml();
}
};
dataGrid.addColumn(textCol);
dataGrid.setColumnWidth(textCol, 75, Unit.PCT);
Column deleteCol = new Column(new ButtonCell()) {
#Override
public String getValue(Item object) {
return "Delete " + object.value;
}
};
deleteCol.setFieldUpdater(new FieldUpdater() {
#Override
public void update(int index, Item object, String value) {
data.getList().remove(index);
data.refresh();
}
});
dataGrid.addColumn(deleteCol);
}
I put this code in a new GWT project and tested it. The DataGrid does not scroll when removing rows.

How to clean an AnnotatedTimeline gwt visualization chart

I am dealing with a problem with annotatedtimelines.
I have to draw some charts depending on the tab that the user is, so when the tab is changed I clean the current chart and draw the new data. But how to do that?
For now I am removing all the rows, but it is not working.
Can someone help me?
here is the code:
...
//Creating Columns
dataTable.addColumn(ColumnType.DATETIME, "Time");
dataTable.addColumn(ColumnType.NUMBER, "Realtime Consumption");
dataTable.addColumn(ColumnType.NUMBER, "Historical Consumption");
//Create options
options.setDisplayAnnotations(false);
options.setDisplayZoomButtons(false);
options.setScaleType(AnnotatedTimeLine.ScaleType.FIXED);
options.setLegendPosition(AnnotatedTimeLine.AnnotatedLegendPosition.SAME_ROW);
options.setAllowRedraw(true);
options.setDisplayRangeSelector(false);
options.setFill(30);
//to parse the time
DateTimeFormat dtf = DateTimeFormat.getFormat("hh:mm:ss");
//For each item of the list
for(int i = 0; i < list.size(); i++){
//get date
Date date = new Date(list.getTimeAt(i));
//get hh:mm:ss
String time = date.getHours()+":"+date.getMinutes()+":"+date.getSeconds();
//add row
dataTable.addRow();
dataTable.setValue(dataTable.getNumberOfRows() - 1, 0, dtf.parse(time));
dataTable.setValue(dataTable.getNumberOfRows() - 1, 2, list.getDataAt(i));
}
/**
* To clean the chart
*/
public void cleanChart(){
//Remove all rows
this.dataTable.removeRows(0, dataTable.getNumberOfRows());
//Redraw the chart
this.draw(this.dataTable, this.options);
}
Thanks,
MaurĂ­cio
It is very strange, but I did it (that seems ok, because I'd create another datatable), and it still not working. The old data continues there.
I have a class that extends AnnotatedTimeLine, and the clean method is now:
/**
* Method to clean the annotated time line
*/
public void clean() {
//Create new table
this.dataTable = DataTable.create();
//Create columns
this.dataTable.addColumn(ColumnType.DATETIME, "Time");
this.dataTable.addColumn(ColumnType.NUMBER, "Data 1");
this.dataTable.addColumn(ColumnType.NUMBER, "Data 2");
//Redraw the chart with the same options
this.draw(this.dataTable, this.options);
}
Any idea?
Thanks!
You need to recreate DataTable for your new data and don't need to do
this.dataTable.removeRows(0, dataTable.getNumberOfRows());
I have something like this
public void reloadChart(List<SharedBean> list, String titleX) {
viz.draw(getChartData(), getOptions(titleX));
}
private DataTable getChartData() {
DataTable data = DataTable.create();
data.addColumn(ColumnType.STRING, "column");
data.addColumn(ColumnType.NUMBER, "value");
data.addRows(list.size());
int row = 0;
int i = 0;
for(SharedBean bean: list){
......
}
return data;
}