PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Sun Nov 10, 2024 7:22 pm

All times are UTC


Forum rules


Please read this before posting on this forum: Forum Rules



Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Thu Jan 18, 2024 4:59 pm 
Offline

Joined: Fri Sep 08, 2023 5:27 pm
Posts: 12
Hi - this could be a user error or possibly a bug. I've been messing with the MigraDoc/PDFSharp tool for report building and ran into an issue. In certain rows of a table, when I MergeRight 1 for a cell, the cells following the 2 merged cells don't display correctly. THANK YOU for your help!

I've included some code/pseudo code so you can see what's up. & some pics. I'm inside a loop, reading records out of a database & writing data into a table. I've separated the writing out of data into it's own method called "AddDataCell". This method takes the current row, the text to write in the cell, the font, the colSpan (used to set the MergeRight value) and an optional CellAlignment. The main method "WriteReportData" calls the database and we loop thru each record grabbing data & calling AddDataCell for each cell. There are 5 columns in the table. The problem happens when I MergeRight cells 2 + 3. Cell 4 is not written out - or possibly, cell 5 overwriting 4. Any ideas of what may be happening. Can I reset or clear some object in between adding cells? I know this is a lot - here's the code/pseudo code:


protected void AddDataCell(Row row, object content, Font font, int colSpan, CellAlignment justify = CellAlignment.Left) {
if (_defaultCell == null) {
_defaultCell = new Cell();
_defaultCell.Borders.Style = BorderStyle.None;
_defaultCell.Borders.Visible = false;
_defaultCell.MergeRight = 0;
}
string text = content.ToString();
text = text.TrimEnd();
Cell cell = _defaultCell.Clone();
cell.Format.Font = font.Clone();
// IMPORTANT: A cell's MergeRight value is 0 based. A colSpan of 1 would be a .MergeRight of 0
cell.MergeRight = colSpan - 1;
switch (justify) {
case CellAlignment.Center:
cell.Format.Alignment = ParagraphAlignment.Center;
break;
case CellAlignment.Right:
cell.Format.Alignment = ParagraphAlignment.Right;
break;
default: // left justification happens by default
break;
}
cell.AddParagraph(text);
row.Cells.Add(cell.Clone()); // even adding a Clone here didn't help (see note below)
/* Buggy:
* if the mergeRight ever set to something other than a 0, it messes up the next cell that is added in some capacity. It seems to skip over it.
* If I reset it here, it will display the next cell that's added but I loose all columnWidths in the table. I've tried everything. I believe
* this tool may be too buggy to use. Note that re-setting the cell to null doesn't help either. Could something still be in memory?
*/
//cell.MergeRight = 0;
//cell = null;

}

protected override void WriteReportData() {
int rowCount = 0;
Font fontDataRow = _pdfDocument.Styles["DataRow"].Font;
Font fontDataHeader = _pdfDocument.Styles["DataHeader"].Font;
Font fontTotal = _pdfDocument.Styles["GrandTotal"].Font;
Section section = _pdfDocument.Sections[0];

// set up our defaultCell and defaultHeaderCell
Cell defaultHeaderCell = new Cell();
defaultHeaderCell.Style = _pdfDocument.Styles["DataHeader"].Name;
Cell defaultCell = new Cell();
defaultCell.Borders.Style = BorderStyle.None;
defaultCell.Style = StyleNames.Normal;

// Set-up the data table & it's columns
Table table = section.AddTable();
table.Borders.Visible = false;

/* The original iText5 report column width calulation was: table.SetWidths(new float[] { 1.5f, 1.5f, 4.5f, 1.0f, 1.0f });
* CELL_BASE_NUM is calculated by using the 0.5f common denominator of the original table.SetWidths values above. Therefore
* we have: [(3 * 0.5), (3 * 0.5), (5 * 0.5), (2 * 0.5), (2 * 0.5)] which is 19. */

int CELL_BASE_NUM = 19;
float baseColWidth = OrientedPageWidth / CELL_BASE_NUM;
table.Columns.AddColumn();
table.Columns[0].Width = baseColWidth * 4;
table.Columns.AddColumn();
table.Columns[1].Width = baseColWidth * 3;
table.Columns.AddColumn();
table.Columns[2].Width = baseColWidth * 8;
table.Columns.AddColumn();
table.Columns[3].Width = baseColWidth * 2;
table.Columns.AddColumn();
table.Columns[4].Width = baseColWidth * 2;
int cellsPerRow = table.Columns.Count;

// Data Rows
Row row = null;
List<IDbDataParameter> spl = new List<IDbDataParameter>();

foreach (IDataRecord idr in new EnumerableDataReader(_css, GetSQLForReport(), spl)) {
try {

// THE FOLLOWING CONTAINS PSUEDO CODE
if (employee has not been encountered before && is not the first employee) {
// first, write out the last employee's grand total info
row = table.AddRow();
AddDataCell(row, "Hours for " + curEmpName + " for responsibilty " + curResponsibility, fontDataHeader, 3, CellAlignment.Right);
AddDataCell(row, curRoleHours.ToString("0.##"), fontDataHeader, 1, CellAlignment.Right);
AddDataCell(row, curEmpRespCost.ToString("C"), fontDataHeader, 1, CellAlignment.Right);

row = table.AddRow();
AddDataCell(row, "Total hours for " + curEmpName, fontDataHeader, 3, CellAlignment.Right);
AddDataCell(row, curEmpHours.ToString("0.##"), fontDataHeader, 1, CellAlignment.Right);
AddDataCell(row, curEmpCost.ToString("C"), fontDataHeader, 1, CellAlignment.Right);
}

normalRate = read employee info from idr

// reset to current employee's info
curEmployeeID = read employee info from idr
curEmpName = read employee info from idr
curResponsibility = read employee info from idr
curEmpHours = 0;
curEmpCost = 0;
curEmpRespHours = 0;
curEmpRespCost = 0;

// begin writing employee's info on page
row = table.AddRow();
AddDataCell(row, curEmpName, fontDataHeader, 1);
AddDataCell(row, curEmployeeID, fontDataRow, cellsPerRow - 1);
row = table.AddRow();
AddDataCell(row, curResponsibility, fontDataHeader, 1);
AddDataCell(row, "Rate: " + normalRate.ToString("C"), fontDataRow, cellsPerRow - 1);
} else if (curResponsibility != read next employee's responsibility from IDataRecord) {
// first, write out the last employee's info
AddDataCell(row, "Hours for " + curEmpName + " for responsibilty " + curResponsibility, fontDataHeader, 3, CellAlignment.Right);
AddDataCell(row, curEmpRespHours.ToString("0.##"), fontDataHeader, 1, CellAlignment.Right);
AddDataCell(row, curEmpRespCost.ToString("C"), fontDataHeader, 1, CellAlignment.Right);

// reset the current employee's responsibility, hours, costs
curResponsibility = read next employee's responsibility from idr;
curEmpRespHours = 0;
curEmpRespCost = 0;
row = table.AddRow();
AddDataCell(row, curResponsibility, fontDataHeader, 1);
AddDataCell(row, "Normal Rate: " + normalRate, fontDataRow, cellsPerRow - 1);
}


/* Buggy: THIS IS WHERE IT BREAKS
* if the mergeRight ever set to something other than a 0 (shown here as the last argument: colSpan of 1 below), it messes up the next cell that is added in some capacity.
* It seems to skip over it. If I reset it here, it will display the next cell that's added but I loose all columnWidths in the table. I've tried
* everything. I believe this tool may be way too buggy.
*/

// MAIN LINE ITEMS for current Employee

row = table.AddRow();
// method below: AddDataCell(Row row, object content, Font font, int colSpan, optional:CellAlignment justify)
AddDataCell(row, "1", fontDataRow, 1);
//AddDataCell(row, "2", fontDataRow, 1);
//AddDataCell(row, "3", fontDataRow, 1);
AddDataCell(row, "2 + 3", fontDataRow, 2); // doing this breaks it - the MergeRight will cause it not display column 4
AddDataCell(row, "4", fontDataRow, 1);
AddDataCell(row, "5", fontDataRow, 1);
double hours = read next employee's responsibility from idr;
double cost = hours * normalRate;

// keep totals going:
curEmpHours += hours;
curEmpRespHours += hours;
totalHours += hours;
curEmpCost += cost;
curEmpRespCost += cost;
totalCost += cost;
}
catch (Exception e) {
AppStd.LogMessage("Error=" + e.ToString());
}
}

if (rowCount == 0) {
row = table.AddRow();
row = table.AddRow();
row = table.AddRow();
AddDataCell(row, "No data for report", fontDataRow, cellsPerRow);
} else {
// FIRST, write out the last employee's info
row = table.AddRow();
// ...
}
}


Attachments:
File comment: Here is the problem: when columns 2 merges with 3, column 4 doesn't display (or 5 overwrites 4). Why? How do I fix this?
merge.png
merge.png [ 104.59 KiB | Viewed 14910 times ]
File comment: Here is an example when columns 2 & 3 are NOT merged
NoMerge.png
NoMerge.png [ 106.48 KiB | Viewed 14910 times ]
Top
 Profile  
Reply with quote  
PostPosted: Thu Jan 18, 2024 6:31 pm 
Offline
PDFsharp Guru
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 1007
Location: CCAA
Looks like a user error at first glance:
You specify MergeRight = 1 for the "2 + 3" cell, so it gets logically merged with the "4" cell and the contents of the "4" will not show.

Add an empty cell after adding the "2 + 3" cell and everything should be OK.
Or pass a column index into your AddDataCell method so that cells will be filled correctly.

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
PostPosted: Fri Jan 19, 2024 3:27 pm 
Offline

Joined: Fri Sep 08, 2023 5:27 pm
Posts: 12
TH-Soft -- thanks for responding. You wrote: You specify MergeRight = 1 for the "2 + 3" cell, so it gets logically merged with the "4" cell and the contents of the "4" will not show.

But I'm writing into cell 2 with a MergeRight of 1, therefore "skipping" only past cell 3 in that row. That makes the next cell to be written into - albeit implicitly so - #4 in that row - doesn't it?

Thanks for walking me thru this!
cb

ps - I do like your idea of adding the cell index explicitly. that may make my problem go away. I'm going to try that but would still appreciate your reply to my question - cb


Top
 Profile  
Reply with quote  
PostPosted: Fri Jan 19, 2024 4:14 pm 
Offline
PDFsharp Guru
User avatar

Joined: Sat Mar 14, 2015 10:15 am
Posts: 1007
Location: CCAA
chris.ball wrote:
That makes the next cell to be written into - albeit implicitly so - #4 in that row - doesn't it?
No, the row still has a cell for each column, even if one cell is ignored.
In your case the MergeRight hides the cell with the text "4".

Each cell has a Column Index. And MergeRight does not change this index.

_________________
Best regards
Thomas
(Freelance Software Developer with several years of MigraDoc/PDFsharp experience)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 18 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Privacy Policy, Data Protection Declaration, Impressum
Powered by phpBB® Forum Software © phpBB Group