大家好,我试图以这种方式从datagridview打印数据,交替的行应该左右打印。我能够打印,但他们没有排队。这是我试图打印的代码。
您可以在此处找到完整的代码
https://drive.google.com/open?id=0ByVjmdncQgagRjZvME9STWJoVHc
using (Font font = new Font("Consolas", 13f))
{
float x = 0;
float y = 0;
for (int row = linesPrinted; row < DGV.Rows.Count; row++)
{
for (int col = 0; col < DGV.ColumnCount; col++)
{
x = 0;
string text = DGV[col, row].FormattedValue.ToString();
if (row % 2 == 0)
{
x += 10;
y += 5;
e.Graphics.DrawString(text, font, Brushes.Black, new PointF(x, y));
}
else
{
x += 45;
y += 5;
e.Graphics.DrawString(text, font, Brushes.Black, new PointF(x, y));
}
}
}
我得到的输出如下
答案 0 :(得分:2)
由于您似乎在尝试在同一行上打印两个不同的行,因此您将必须跟踪列1的“Y”值开始的位置,这将有助于排列第2列。另一个问题是当有多个页面要打印时,当前代码只打印一页。
当循环DataGridView
打印行时,我们到达页面末尾,我们需要再次调用PrintPage
方法。在当前形式中,PrintPage
方法将从DataGridView
的第一行(0)开始打印,并且它将为每个新页面执行此操作。随之而来的是无限循环,因为每个新页面都会从第一行开始。全局int
变量dgvRowIndex
应该修复此问题,以便每次打印下一页时我们都不会从头开始。
我很难打印多个页面,但@LarsTech解决方案在Print multiple datagridview pages
处理得很好为了提供帮助,下面是一种简单打印数据网格视图的一行的方法。该方法需要rowIndex
来确定DataGridView
中要使用的行,printX
值以指示起始左侧打印值,printY
值来指示垂直位置要开始打印此行,lineIncrement
用作文本的“前导”值,最后用PrintPageEventArgs
变量e
来绘制文本。
private void printRow(int rowIndex, float printX, float printY, float lineIncrement, PrintPageEventArgs e) {
for (int col = 0; col < dataGridView1.ColumnCount; col++) {
string text = dataGridView1[col, rowIndex].FormattedValue.ToString();
e.Graphics.DrawString(text, font, Brushes.Black, new PointF(printX, printY));
printY += lineIncrement;
}
}
既然我们有一个方法可以将DatagridView
中的单行打印到打印文档中的一列中,那么将列打印为行并将行排成一行应该会更容易。首先如前所述,我们需要一个全局变量来跟踪DataGridView
行索引,同时循环遍历它。每次调用dgvRowIndex
方法时都会使用此全局变量PrintPage
。我还将字体变量添加为全局变量。
// global variables
int dgvRowIndex = 0;
Font font = new Font("Consolas", 13f);
以下是打印每页的PrintPage
方法。大多数变量的名称都是不言自明的。 pageHeight
用于确定何时需要新页面。两列LeftColX
和RightColX
是每列的两个水平(X)起点。 curY
跟踪打印页面上的垂直(Y)位置,用于将其值与pageHeight
进行比较,并在需要时启动新页面。 lineIncrement
用作每个新行的“前导”值。 spaceBefore
用于在两个打印行之间添加额外的垂直空间。最后,如前所述,我们需要在打印新的“第1列”时跟踪垂直“Y”值。 column2YValue
用于此目的,并在打印第二列时作为起始“Y”值发送到PrintRow
方法。
当while循环开始循环遍历DataGridView
的行时,会检查此行是否在第1列或第2列。如果dgvRowIndex
在第1列,那么我们需要保存此起始“Y”column2YValue
以在打印第二列时使用。如果dgvRowIndex
位于第2列,那么我们只需再次调用printRow
方法,但这次我们会从上一列column2YValue
中传递起始“Y”值。添加了额外的垂直空间,dgvRowIndex
递增以转到下一行,然后检查是否需要添加另一个页面。这里进行简单检查以查看当前“Y”值curY
是否超过保证金,如果是,则我们需要指示需要新页面然后返回。 return
只是简单地启动PrintPage
方法,这应该按预期工作,因为我们现在有一个全局变量dgvRowIndex
,以避免从DataGridView
的开头开始。希望这会有所帮助。
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e) {
float pageHeight = e.MarginBounds.Height;
float leftColX = 10;
float rightColX = 145;
float curY = 10;
float lineIncrement = 16;
float spaceBefore = 24;
float column2YValue = curY;
while (dgvRowIndex < dataGridView1.Rows.Count) {
if (dgvRowIndex % 2 == 0) {
column2YValue = curY;
printRow(dgvRowIndex, leftColX, curY, lineIncrement, e);
} else {
printRow(dgvRowIndex, rightColX, column2YValue, lineIncrement, e);
curY += spaceBefore;
}
dgvRowIndex++;
if (curY > pageHeight) {
e.HasMorePages = true;
return;
}
curY += spaceBefore;
}
}
编辑以处理多个列和多行。
正如我评论的那样,为了打印多列,代码需要跟踪页面上的打印“X”值。我们的想法是在相同(打印)行(y值)上保持打印,直到“X”值超过右边距。
另一个更改解决了从哪里开始下一个打印组/网格行的问题。当代码调用printRow
时,在调用之前不知道网格行可能有多少列。如果网格有三列,四列或十列,则代码将打印该行数。如果每个网格行中有10列...网格中的每一行将有10个“打印”行。由于printRow
将循环遍历要打印的列,因此它用于返回此“下一个”“Y”打印行值。
跟踪下面的代码,遍历网格行,首先打印当前行,然后根据网格中的列数设置下一个“打印”行nextRowYStart
。
下一个if
语句会检查页面右侧是否有足够的空间来打印另一列。如果页面上有足够的空间用于其他列,则curX
只会移动到下一列。如果空间不足,则“X”值curX
将重置为最左侧(起始)列,curY
将设置为nextRowYstart
以向下移动到下一个打印行,并添加了一些垂直空间。然后进行检查以查看新的打印行“Y”值curY
是否超过下边距。如果是,那么我们开始一个新的页面。否则,只需打印网格的下一行。
代码假定您要打印所有列,但是如果您只想打印前X列,则会添加stopColumn
变量,以便您可以决定要打印的第一列中有多少列。我猜这可能是你在找什么。希望它有所帮助。
private void printDocument1_PrintPage(object sender, PrintPageEventArgs e) {
//int stopColumn = 3;
int stopColumn = dataGridView1.Columns.Count;
float pageHeight = e.MarginBounds.Height;
float pageWidth = e.MarginBounds.Width;
float startX = 50;
float startY = 50;
float columnWidth = 150;
float curX = startX;
float curY = startY;
float lineIncrement = 16;
float spaceBefore = 24;
float nextRowYStart = curY;
while (dgvRowIndex < dataGridView1.Rows.Count) {
nextRowYStart = printRow(dgvRowIndex, curX, curY, lineIncrement, stopColumn, e);
if (curX + columnWidth > pageWidth) {
// start a new PRINT group/row
curX = startX;
curY = nextRowYStart;
curY += spaceBefore;
if (curY > pageHeight + spaceBefore) {
dgvRowIndex++;
e.HasMorePages = true;
return;
}
} else {
curX += columnWidth;
}
dgvRowIndex++;
}
}
更新了printRow方法
private float printRow(int rowIndex, float printX, float printY, float lineIncrement, int stopCol, PrintPageEventArgs e) {
for (int col = 0; col < dataGridView1.ColumnCount; col++) {
if (col < stopCol) {
string text = dataGridView1[col, rowIndex].FormattedValue.ToString();
e.Graphics.DrawString(text, font, Brushes.Black, new PointF(printX, printY));
printY += lineIncrement;
}
else {
break;
}
}
return printY;
}