Reputation: 13
I'm trying to export a datagrid to PDF with iTextSharp and need to make a page break when one column changes. I have this code
using (FileStream stream = new FileStream(savefiledialoge.FileName, FileMode.Create))
{
try
{
pdfdoc = new Document(PageSize.A4, 10f, 10f, 10f, 0f);
PdfWriter writer = PdfWriter.GetInstance(pdfdoc, stream);
pdfdoc.SetPageSize(PageSize.A4.Rotate()); // horizontal
pdfdoc.Open();
Encabezado();
for (int i = 0; i <= dataGridView1.RowCount; i++)
{
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
if (dataGridView1.Rows[i].Cells["Warehouse"].Value.ToString() == dataGridView1.Rows[i + 1].Cells["Warehouse"].Value.ToString())
{
pdftable.AddCell(new Phrase(dataGridView1.Rows[i].Cells[j].Value.ToString(), text));
}
else
{
pdftable.AddCell(new Phrase(dataGridView1.Rows[i].Cells[j].Value.ToString(), text));
pdfdoc.Add(pdftable);
pdfdoc.NewPage();
pdftable.DeleteBodyRows();
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "error occured ", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
but I have two problems, one of the rows is added in a new page
and the compilation gives me an error:
"Index was out of range, must be nonnegative and less than the size of the collection."
Upvotes: 1
Views: 516
Reputation: 95918
You have the case differentiation inside your loop over the columns:
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
if (dataGridView1.Rows[i].Cells["Warehouse"].Value.ToString() == dataGridView1.Rows[i + 1].Cells["Warehouse"].Value.ToString())
{
pdftable.AddCell(new Phrase(dataGridView1.Rows[i].Cells[j].Value.ToString(), text));
}
else
{
pdftable.AddCell(new Phrase(dataGridView1.Rows[i].Cells[j].Value.ToString(), text));
pdfdoc.Add(pdftable);
pdfdoc.NewPage();
pdftable.DeleteBodyRows();
}
}
The effect: Let's assume i
currently is the value for the last row for a given warehouse. Thus, inside the j
loop above you'll go into the else
branch all the time, so
j == 0
your code already adds the table with the still incomplete row i
("incomplete" as only the cell for the first column has been added) to the document. iText does not draw the incomplete row i
but goes to the next page with that single column still in the table object.j
before the final column, the row still is incomplete, so pdfdoc.Add(pdftable)
adds nothing to the page but stores the new cells in the table object. pdfdoc.NewPage()
does not create yet another page as the current page still is empty.j
the row i
finally is complete, so pdfdoc.Add(pdftable)
adds a single-row table and pdfdoc.NewPage()
creates yet another new page.You should instead first add the complete current row i
to the table in the body of your loop over i
and only thereafter test whether a change of warehouse will occur in the next row; i.e. replace the quoted code above by
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
pdftable.AddCell(new Phrase(dataGridView1.Rows[i].Cells[j].Value.ToString(), text));
}
if (i == dataGridView1.RowCount - 1)
{
pdfdoc.Add(pdftable);
}
else if (dataGridView1.Rows[i].Cells["Warehouse"].Value.ToString() != dataGridView1.Rows[i + 1].Cells["Warehouse"].Value.ToString())
{
pdfdoc.Add(pdftable);
pdfdoc.NewPage();
pdftable.DeleteBodyRows();
}
Concerning the "Index out of range":
On the other hand, as @Bruno already mentioned, the loop over i
should stop earlier, instead of
for (int i = 0; i <= dataGridView1.RowCount; i++)
use
for (int i = 0; i < dataGridView1.RowCount; i++)
Upvotes: 1