I'm creating a PDF document using iTextSharp. I see how to create a new table with a number of columns but I can't see anyway to dynamically add a new column. The problem I have is I'm not going to know the number of columns I need straight away, so need to keep adding them
Can somebody please enlighten me or am I going to have to re-create the table each time I need to add a column?
Thanks
Mat
Wouldn't it then make sense to create an intermediate model which contains the table you want, and is capable of then creating the PDF table for you?
I know it sounds like a lot of work, but in the long run it should help in that you would be able to dynamically alter the rows and columns as you build them, and then at the end, simply "compile" the table and spit out the PdfPTable object?
PdfPTable tables are immutable as far as column count goes once created.
The only workaround I can think of is to start with a Whole Bunch of columns and... nope that won't work either. You cannot even add cells to an existing row. I was thinking you could play around with the column spanning to mask your extra columns and adjust them as you added more cells to the rows, but that won't work either.
You must rebuild the table when adding columns. No way around it.
I strongly recommend you figure out how to determine your column count before creating the table in the first place... even if you have to "dry run" through your data. Use some intermediate format (String[][] or whatever) to keep your data, then build the table from that, not the data as it comes to you. Or at least track how many columns you'll need.
Given a huge amount of data, a single pass may not be practical/possible. But rebuilding your whole table several times can't be much better. That's really a performance tuning question that only you have the information to answer.
ITextSharp tables work in a different way to HTML tables (which I guess you're used to).
All you need to tell it is the number of columns you have and then keep adding cells.
Say you create a pdfptable with 5 columns. The 5th cell you add will be on the first row and the 6th cell will be in the 1st column on your 2nd row.
The only downside to this is if you need to add rows where not all the cells are populated but I usually get around this by just adding an empty cell or a cell with a space in it.
Related
I have a list view in WinForms that works and looks fine. However, the grid lines are formatted in such a way that there's no separation between the column headers and the first row of data. This makes it look like the first row of data is part of the column headers. You can see what I mean here:
Is there any way I can format the list to stop this from happening, and make it look 'proper'? Thanks for any help.
I see you're displaying "data" to users in a grid - except you're using a ListView - which is really intended for filesystem display, not data.
I recommend you switch to using DataGridView (avoid System.Windows.Forms.DataGrid as it's older and doesn't let you (easily) control the data being displayed).
Also, protip for usability: if a table cell contains numeric data then it should be formatted with Right alignment, otherwise give it a Left alignment - avoid Middle/Center alignment in non-header table cells as it makes it difficult to visually scan a table.
I've been playing around with this, but I just can't get it to work. I have a table in Microsoft Word, and in this table is a mailmerge field which my C# program selects.
I'd like to delete the row which contains the field. I tried this:
app.Selection.SelectRow();
app.Selection.Delete();
Where app is an instance Microsoft.Office.Interop.Word.Application.
As written, this code deletes the text inside the table, but leaves an empty table row behind. How can I delete the table row itself?
When you have a Range or Selection, in most cases you can address the "containing" level like this:
app.Selection.Rows[1]
(Since I'm on a mobile device I can't check whether you can use .Delete() directly or whether you need .Range.Delete())
Similarly, Selection.Tables[1] would pick up the table around the selection and Selection.Paragraphs[1] the paragraph around the selection.
Note that, unless what you want to do simply won't work any other way, you should use the Range object. There will be less screen-flicker, execution will be faster and your code more predictable.
Given a data set containing multiple rows, from within a .NET console application I need to generate a report on a single page for each row, sending those pages directly to the printer.
I am attempting to use Microsoft Report for this by attaching it to a data set and placing TextBoxes where I wish. Generating the report and sending it to the printer are not a problem. Unfortunately, the data only seems to be available in aggregates -- First, Sum, Last, Max, etc. I cannot latch the text box to a bare field.
Some poking around here and other sites seems to address this, but only when the data is presented in a table. One post even said without elaboration, "My mistake was using Text Boxes"
Am I using the wrong tool for what I am attempting to accomplish?
I ran into the same problem and managed to solve it. The solution seems a little convoluted to me so don't quote me on the "right" way to do this, but here is what I did:
Make sure you have a Dataset defined for your report.
Add a "Table" control to the report. This seems to be needed in order to iterate the rows in your Dataset.
Delete the header row and two of the default columns from the table so that you are left with a single row with a single column.
Expand the table to the width of your layout and make it as tall as you will need for your "free form" layout.
By default, there is a TextBox inside the table cell. Right-click the empty table cell and choose "delete" to remove that TextBox.
Drag a "Rectangle" control into the empty table cell. It seems to automatically "dock" to the width/height of the table cell.
Now you should be able to drag the fields from your DataSet (TextBoxes, etc) into the Rectangle to produce the desired layout.
Note that I am in the early stages of using this approach so I'm not sure if I am going to hit any walls... but for a basic report that uses TextBoxes and a page break after each "row" it seems to be working ok.
Or you try to use a list.
In the list you can arange textboxes (and other controls) as you want and they will be filled for each record in the recordset.
This work for me. :-)
I'm using a GridView that is bound to an object (an entity). The grid can be filtered and otherwise customized in terms of the data it shows. The rows, columns and more specifically cells will be formatted using some rules, but also from the user specifically setting formatting options.
My questions is about the best way to recall the chosen formatting for specific cells. Currently my best method is to store an id for each cell that looks up all of the formatting for that cell (i.e. ForeColor, BackColor, FontWeight etc).
Another way would be to create a new table (called say Formatted_Cells) that stores the id and column name of the table in question, and then the formatting options. This would involve checking the Formatted_Cells table each time a cell is processed to check for formatting. It is quite a bit of processing (similar to the above method). If I did this I could flag any rows that have custom formatting, and if they do not I wouldn't need to check the Formatted_Cells table which does provide an advantage over remembering formatting for EVERY cell, when the vast majority will not have any custom formatting.
Is there a better way? I don't think I can use Serialization to help as the grid is loaded from the database which may be modified elsewhere. But perhaps I'm missing something obvious?
Much appreciated.
I'd suggest an additional table also.
Two possible solutions come to mind:
1- Do the formatting in two passes. First load the grid normally, then read Formatted_Cells table from database, find styled rows in grid and apply special styling.
2- When quering database for Cells, add Formatted_Cells table with left join. When loading grid, check for additional columns that might come from left join, apply those. If no additional columns, style normally.
I'm working with a structure of tables; i have several small tables i want to include in a bigger table, inserting them into tablecells of this bigger table, but i don't know how to do it.
Is there any way to transform the small tables to code and use the TableCell.Text = "code of small table" or something like that?
I guess it is possible to do dynamically, but i can't figure out how to...
In .net to add control to prent control there is method Controls.Add() so your code will be
TableCell.Contols.Add(newtable);