If I run the same code with the same data, I get inconsistent results: it appears that data in a cell with a Style.Font of Calibri 9pt regular occasionally stops being rendered when the Grid.Draw method is executed, but if I change the cell to render as Calibri 9pt Bold, for example, it will actually render fine when Grid.Draw is executed, while other cells are not rendered because of the use of the regular font.
Also it tends to be an all or nothing problem: I generally create 4 different Grids on the document, and when this fails, it always fails on all the Grids in the document.
I populate the data by row and column, and have dumped the data and a description of the appropriate Cell fonts after the draw, and they all appear exactly as they do when it works.
I cannot guarantee a reproduction of the bug, but if I generate enough versions of the document, it will eventually break. On our live system this is proving a real problem. I can't put all the code up here at the moment to reproduce the problem, but I can show you the basic outline.
I have a PDFWriter class, which contains a method that effectively caches the fonts in a list, but I started off just creating new instances of the font as required:
- Code: Select all
public PdfTrueTypeFont GetFont(string EncodedFontName)
{
if (!Fonts.ContainsKey(EncodedFontName))
{
string fontName = "";
int j = 0;
string sizeString = "";
int fontSize = 9;
bool doName = true;
foreach (char C in EncodedFontName)
{
if (doName)
{
if (!char.IsDigit(C))
fontName = fontName + EncodedFontName.Substring(j, 1);
else
{
doName = false;
sizeString = sizeString + EncodedFontName.Substring(j, 1);
}
}
else
{
if (char.IsDigit(C))
sizeString = sizeString + EncodedFontName.Substring(j, 1);
else
break;
}
j++;
}
if (sizeString != "")
fontSize = int.Parse(sizeString);
FontStyle fontStyle = FontStyle.Regular;
if (EncodedFontName.ToLower().EndsWith("bold"))
{
fontStyle = FontStyle.Bold;
}
else if (EncodedFontName.ToLower().EndsWith("italic"))
{
fontStyle = FontStyle.Italic;
}
PdfTrueTypeFont ActualFont = new PdfTrueTypeFont(new Font(fontName, fontSize, fontStyle));
Fonts.Add(EncodedFontName, ActualFont);
}
return Fonts[EncodedFontName];
}
And the class uses the following function to write the grid to the pdf file:
- Code: Select all
public void WriteTable(string[][] dataSource, DMSPDFTableTypes TableType, string TableTitle = null, bool AllowBreak = true)
{
//DataDump(dataSource);
float TempY = Y;
//Cache this for the total is shown on the RHS.
float TempLeft = Left;
int HeaderOffset = 0;
if ((TableType == DMSPDFTableTypes.OddCellTitles & TableTitle != null) | (TableType == DMSPDFTableTypes.Guests) | (TableType == DMSPDFTableTypes.TitleOneColumn))
{
HeaderOffset = 1;
TempY = TempY + 12f; //title row height
}
int ColumnCount = -1;
if (dataSource != null)
if (dataSource.Length > 0)
ColumnCount = dataSource[0].Length;
if (ColumnCount == -1)
{
switch (TableType)
{
case DMSPDFTableTypes.SupplierCosts:
ColumnCount = 3;
break;
case DMSPDFTableTypes.Guests:
ColumnCount = 4;
break;
default:
ColumnCount = 2;
break;
}
}
lock (GridLock)
{
PdfGrid grid = CreateGridWithHeading(TableType, ColumnCount, TableTitle, HeaderOffset);
bool bHeaderOnly = true;
for (int r = 0; r < dataSource.Length; r++)
{
TempY = TempY + 12f;
if ((TempY > Height - BottomMargin) && AllowBreak)
{
if (!bHeaderOnly)
{
grid.Draw(PageBase, new RectangleF(Left, Y, Width - Left, Height - Y));
//DumpGrid(grid);
}
PageBase = Section.Pages.Add();
StartPage();
Top = LowerTopMargin;
TempY = Y + 12f; //Cover header
grid = CreateGridWithHeading(TableType, ColumnCount, TableTitle, HeaderOffset);
TempY = TempY + 12f; //Cover this new line.
}
PdfGridRow row = grid.Rows.Add();
bHeaderOnly = false;
row.Height = 12f;
for (int c = 0; c < dataSource[r].Length; c++)
{
row.Cells[c].Value = dataSource[r][c];
row.Cells[c].Style.TextBrush = PdfBrushes.Black;
switch (TableType)
{
case DMSPDFTableTypes.OddCellTitles:
if (c % 2 == 0)
row.Cells[c].Style.Font = GetFont("Calibri9ptBold");
else
row.Cells[c].Style.Font = GetFont("Calibri9pt");
break;
case DMSPDFTableTypes.OddCellTitleTotals:
if (c % 2 == 0)
row.Cells[c].Style.Font = GetFont("Calibri9ptBold");
else
{
row.Cells[c].Style.Font = GetFont("Calibri9pt");
row.Cells[c].Style.BackgroundBrush = PdfBrushes.LightSteelBlue;
}
break;
case DMSPDFTableTypes.Guests:
if ((c == 0) && (r == 0))
row.Cells[c].Style.Font = GetFont("Calibri9ptBold");
else if (c == 1)
{
row.Cells[c].Style.Font = GetFont("Calibri9pt");
row.Cells[c].Style.Borders.Top = new PdfPen(Color.Transparent);
row.Cells[c].Style.Borders.Bottom = new PdfPen(Color.Transparent);
}
else
row.Cells[c].Style.Font = GetFont("Calibri9pt");
break;
case DMSPDFTableTypes.SupplierCosts:
if (r == 0)
{
row.Cells[c].Style.Font = GetFont("Calibri9ptBold");
row.Cells[c].Style.BackgroundBrush = PdfBrushes.LightSteelBlue;
}
else
row.Cells[c].Style.Font = GetFont("Calibri9pt");
break;
default:
row.Cells[c].Style.Font = GetFont("Calibri9pt");
break;
}
}
}
grid.Draw(PageBase, new RectangleF(Left, Y, Width - Left, Height - Y));
Y = TempY;
//replace this for the total is shown on the RHS.
Left = TempLeft;
//DumpGrid(grid);
}
}
For reasons I do not particularly want to go in to, but concerning presenting a header and footer optionally on the document, the page has margins of 0, and I maintain the actual position on the page, and margins in internal properties, hence the Height/Width/Y, etc.
Is there anything anybody else can see that is obviously going to be problematic here? Has anybody else experienced similar problems? Does anybody else have a similar issue, and hence a solution?
I will endeavour to create a smaller but fuller version of the code that exhibits the same problem, so you could try running it, but apart from the fact that this is being run over multiple threads, there's little else I can say. The Grid looks ok, but sometimes one particular font just no longer renders. And If I change the line of code for OddCellTitles from
- Code: Select all
row.Cells[c].Style.Font = GetFont("Calibri9pt");
- Code: Select all
row.Cells[c].Style.Font = GetFont("Calibri9ptBold");