我能够将完整的gridview导出为pdf,但我不明白如何定位特定行并在单击按钮时使用itextsharp将其导出为pdf
这是我的代码下面导出到pdf在那里我能够导出完整的gridview
private void gvSamplereports_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == gvSamplereports.Columns["btnPDFsingle"].Index)
{
DateTime PrintTime = DateTime.Now;
if (gvSamplereports.Rows.Count > 0)
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "PDF (*.pdf)|*.pdf";
sfd.FileName = "SampleDataReports_" + PrintTime.ToShortDateString() + ".pdf";
bool fileError = false;
if (sfd.ShowDialog() == DialogResult.OK)
{
if (File.Exists(sfd.FileName))
{
try
{
File.Delete(sfd.FileName);
}
catch (IOException ex)
{
fileError = true;
MessageBox.Show("It wasn't possible to write the data to the disk." + ex.Message);
}
}
if (!fileError)
{
try
{
PdfPTable pdfTable = new PdfPTable(gvSamplereports.Columns.Count);
pdfTable.DefaultCell.Padding = 3;
pdfTable.WidthPercentage = 100;
pdfTable.HorizontalAlignment = Element.ALIGN_CENTER;
//Below line is to add the header column name on each page of pdf
pdfTable.HeaderRows = 1;
foreach (DataGridViewColumn column in gvSamplereports.Columns)
{
Font fon = FontFactory.GetFont("ARIAL", 6);
fon.SetStyle(1);
PdfPCell cell = new PdfPCell(new Phrase(column.HeaderText, fon));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
pdfTable.AddCell(cell);
}
foreach (DataGridViewRow row in gvSamplereports.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
Font fon = FontFactory.GetFont("ARIAL", 6);
PdfPCell cell2 = new PdfPCell(new Phrase(cell.Value?.ToString(), fon));
cell2.HorizontalAlignment = Element.ALIGN_CENTER;
pdfTable.AddCell(cell2);
//pdfTable.AddCell(cell.Value.ToString());
}
}
using (FileStream stream = new FileStream(sfd.FileName, FileMode.Create))
{
Document pdfDoc = new Document(PageSize.A4, 30f, 30f, 100f, 50f);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, stream);
//PDFFooter is class created for adding header and footer in the pdf
writer.PageEvent = new PDFFooter();
pdfDoc.Open();
pdfDoc.Add(pdfTable);
pdfDoc.Close();
stream.Close();
}
MessageBox.Show("Data Exported Successfully !!!", "Info");
}
catch (Exception ex)
{
MessageBox.Show("Error :" + ex.Message);
}
}
}
}
else
{
MessageBox.Show("No Record To Export !!!", "Info");
}
}
}
我已经添加了图片供参考,一旦我点击按钮,我想使用C# winform中的Itextsharp导出带有标题列名称的单行,在PDF中导出的数据应该看起来像
下面的图片
1条答案
按热度按时间lndjwyie1#
将数据与其显示方式分开
在现代编程中,数据(=模型)与它与操作员(=视图)的通信方式是分开的。这样做的好处是,如果您决定以不同的方式显示模型,例如,如果您想以图形而不是表格的形式显示数据,则可以重用模型。
为了使模型与视图匹配,需要一个适配器类。这个适配器类通常被称为Viewmodel。这三个类一起缩写为MVVM。考虑阅读一些关于这个的背景信息。
当使用Winforms和DataGridView时,人们倾向于直接处理行和单元格,而不是将数据与其显示方式分离。这通常会导致很多问题。除了不能在没有窗体的情况下对数据进行单元测试之外,不能在其他窗体中重用数据,也不能在不更改DataGridView的情况下更改数据。
Winforms使用属性
DataGridView.DataSource
支持MVVM。如何轻松高效地访问DataGridView的数据?
唉,您忘记告诉我们DataGridView中有什么,而且我无法从您的代码中提取所显示的内容。因此,对于该示例,让我们假设您显示
Products
集合的几个属性:您可能不想显示所有属性。
因此,您当然有一个过程来获取最初要显示的产品:
实施不在问题的范围内。
您已经使用Visual Studio设计工具加入了
DataGridView
,以及您要显示的每个Product属性的DataGridViewColumn
。您必须定义哪个DataGridViewColumn会显示哪个属性的值。这可以使用设计工具来完成。我通常会在建构函式中使用nameof
来完成。使用
nameof
的好处是,如果以后你决定改变属性的名称,它会自动在这里改变。编译器会检测到键入错误。现在要显示所有产品,您所要做的就是将ProductsToDisplay赋值给'dataGridView1.DataSource:
您的数据很快就会显示出来。
但是,如果操作员编辑表,数据不会更新。如果您希望这样,您必须将必须显示的产品放入一个实现
IBindingList
的对象中。幸运的是,已经有这样一个类,命名为BindingList<T>
并不奇怪将下列属性加入至表单:
现在,操作员所做的所有更改都将在BindingList中自动更新:单元格的更改,以及添加和删除的行。
要访问编辑的表格,例如在操作员按下OK按钮后:
回到你的问题
但我不知道如何定位特定行
BindingList<T>
没有实现IList<T>
。设计者们发现直接访问this.DisplayedProducts[4]
没有什么用处。毕竟:如果操作符可以重新排列行,您就不知道索引为[4]
的行中有什么。但是,您可能希望将产品作为序列进行访问。因此,实现了
ICollection<T>
。如果要访问
current
行或selected rows
,请考虑将以下属性添加到窗体中:这将返回当前产品,如果未选择任何内容,则返回null
因此,要在操作员按下Ok按钮后访问所选产品:
还有改进的空间
如果我看一下您的代码,我觉得如果操作员单击名为
btnPDFsingle
的列中的单元格(为什么不使用一个可以解释列显示内容的名称呢?),那么您将执行以下操作:PdfPTable
并用DataGridView的内容填充它你决定在一个过程中完成所有的工作,这使得单元测试变得很困难。你不能重用代码的任何部分,如果你改变了代码的一部分,很难检测出代码的哪些部分也必须改变。
注意:如果您决定保存一些不同的产品,只保存选定的产品,或者只保存前10个产品,或者只保存非食品产品,您所要做的就是更改此方法。其他方法不知道,也不必知道保存了哪些产品。
顺便说一下,您是否注意到,直到现在我还没有提到产品保存为PDF?如果以后您决定将其保存为XML、CSV或纯文本,这些过程都不必更改。
您看到了吗?要创建PdfPTable,我不再需要访问DataGridViewRows或Cells了吗?如果您决定更改PdfPTable的布局,则只更改此过程。外部的方法不了解表的内部格式。易于单元测试、易于重用、易于更改。
您看到了吗?因为所有的小程序,每个程序只有一个特定的工作。如果您想要进行小的变更(例如保存为XML),可以使用类似的工作来取代这个工作,公寓测试这个工作会容易得多。您可以以不同的形式重复使用这些程序中的每一个。因为您有适当的公寓测试,所以您不必担心这些程序会有未预期的行为。
结论:
不要让你的程序太大。每个程序都应该有一个明确的任务。这就是所谓的关注点分离的一部分。考虑阅读一些关于这方面的背景信息。