Click here to Skip to main content
15,886,724 members
Please Sign up or sign in to vote.
1.50/5 (2 votes)
See more:
I have a datagridview and foreach CHECKED row it prints the value of a checked row in a page ,if I check 10 rows , the software generates 1 document with 10 pages one to each row. now the software prints one row per page But I need to print TWO ROWS per PAGE how can handle this? part of the code below...

C#
var allCheckedRows = this.dgv1.Rows.Cast<DataGridViewRow>()
                              .Where(row => (bool?)row.Cells[0].Value == true)
                              .ToList();

            if (allCheckedRows.Count > currentPrintingRowIndex)
            {
                var builder = new StringBuilder();

                var currentCheckedRow = allCheckedRows[currentPrintingRowIndex];

                var cellValues = currentCheckedRow.Cells.Cast<DataGridViewCell>()
                        .Where(cell => cell.ColumnIndex > 0)
                        .Select(cell => string.Format("{0}", cell.Value))
                        .ToArray();

                builder.Append(string.Join(",", cellValues));


                string ldp = builder.ToString();
                string[] everyhow = ldp.Split(',');


============================================================
//Current code is

C#
private int currentPrintingIndex = 0;

List<string>CheckedValues = new List<string>();

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
        {

 var CheckedValues = this.dgv1.Rows.Cast<DataGridViewRow>()
              .Where(row => (bool?)row.Cells[0].Value == true)
              .ToList();

 if (CheckedValues.Count > currentPrintingIndex)
              {
                 var currentValue = CheckedValues[currentPrintingIndex];


                 e.Graphics.DrawString(currentValue.ToString(), fdiag, Brushes.Black, 10, 10);



                 currentPrintingIndex += 1;
             }

 if (CheckedValues.Count > currentPrintingIndex)
             {
                var currentValue = CheckedValues[currentPrintingIndex];



                e.Graphics.DrawString(currentValue.ToString(), fdiag, Brushes.Black, 160, 10);


               currentPrintingIndex += 1;
             }

              e.HasMorePages = CheckedValues.Count > currentPrintingIndex;

}


Thanks in Advance!
Posted
Updated 2-Oct-15 7:06am
v4
Comments
Sergey Alexandrovich Kryukov 28-Sep-15 16:18pm    
What's the difference, one or two rows? Write any number of rows you want? What's the problem?
—SA
JoaniSilva 28-Sep-15 16:48pm    
the difference is that now the printing is just a single row per document for exemple: into an array I have 3 rows like row1 value = 000001, row2 value =000002 and row3 value = 000003 and I need to print Row1 and Row2 in the same Document and Row3 in the NEXT Document. I really need Two Rows per Document, if I have 40 Rows I will need to print in 20 Documents!...the sequence is 000001 and 000002 in a document1 and 00003 plus 000004 in the Document2! thanks in advance!!!!

a quick sketch for one possible strategy: (not tested/working code !)
C#
public void ProcessCheckedRows(DataGridView dgv1)
{
    // code by OP
    var allCheckedRows = dgv1.Rows
         .Cast<datagridviewrow>()
         .Where(row => (bool?)row.Cells[0].Value == true)
         .ToList();
    
    StringBuilder builder = new StringBuilder();
    
    for(int i = 0, i < allCheckedRows.Count - 1; i += 2)
    {
       builder.Clear();
      
       builder.Append(ProcessRow(allCheckedRows[i]));
       builder.Append(ProcessRow(allCheckedRows[i + 1]));
    
       PrintDocument(builder);   
    }
    
    // handle a last single row
    if(allCheckedRows % 2 == 1)
    {
       builder.Clear();
       builder.Append(ProcessRow(allCheckedRows.Last()));
       PrintDocument(builder); 
    }
}

public string ProcessRow(DataGridViewRow row)
{
   // row => string
}

public void PrintDocument(StringBuilder sb)
{
   // print
}
 
Share this answer
 
v6
Comments
BillWoodruff 28-Sep-15 19:09pm    
Thanks for the assist, Matt ! I simply forgot to increment the for-loop counter by #2 instead of #1 :)
Maciej Los 29-Sep-15 12:40pm    
5ed!
A variation on BillWoodruff's solution that allows generalization to an arbitrary number of "rows" per "Document" and works with the lazy behavior of IEnumerable<T>:
C#
public void ProcessCheckedRows(DataGridView dgv1)
{
    // code by OP
    var allCheckedRows = dgv1.Rows
         .Cast<DataGridViewRow>()
         .Where(row => (bool?)row.Cells[0].Value == true);
    
    StringBuilder builder = new StringBuilder();
    
    const int RowsPerDocument = 2;
    int rowCount = 0;
    foreach (var row in allCheckedRows)
    {
       builder.Append(ProcessRow(row));
       if (++rowCount == RowsPerDocument)
       {
          PrintDocument(builder);
          builder.Clear();
          rowCount = 0;
       }
    }
    
    // handle possible last document with less than RowsPerDocument rows
    if (rowCount > 0)
    {
       PrintDocument(builder); 
    }
}

Side note: The .Where() looks like it could throw an exception if the Value is null. There's no check for .HasValue!
Perhaps, what is wanted is:
C#
var allCheckedRows = dgv1.Rows
     .Cast<DataGridViewRow>()
     .Where(row => ((bool?)row.Cells[0]).GetValueOrDefault(false));
     // or .GetValueOrDefault(true) depending on how null should behave...
     // comparison with true is unnecessary, the value at this point is already bool
Nevermind the Side note!
=================================================
Edit: MTH based on your updated code above, try something like:
C#
private int currentPrintingIndex = 0;
 
List<string>CheckedValues = new List<string>();
 
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
 
 IEnumerable<DataGridViewRow> CheckedValues = this.dgv1.Rows.Cast<DataGridViewRow>()
              .Where(row => (bool?)row.Cells[0].Value == true)
              .Skip(currentPrintingIndex);
 IEnumerator<DataGridViewRow> cve = CheckedValues.GetEnumerator();
 int count = 0;
 int pos = 10;
 while ((e.HasMorePages = cve.MoveNext()) && count++ < 2)
 {
   var cellValues = cve.Current.Cells.Cast<DataGridViewCell>()
                    .Skip(1)    //instead of .Where(cell => cell.ColumnIndex > 0)
                    .Select(cell => cell.Value.ToString())
                    .ToArray();
   // at .NET 4, string.Join can take IEnumerable<string> so the .ToArray() would be unnecessary
   e.Graphics.DrawString(string.Join(",", cellValues), fdiag, Brushes.Black, pos, 10);
 
   currentPrintingIndex += 1;
   pos += 150;
 }
}
 
Share this answer
 
v4
Comments
BillWoodruff 28-Sep-15 20:49pm    
Your solution gets my 5 !

Hi Matt, this is code I typically use for "chunking" a List into an IEnumerable of IEnumerables inclusive of any "remainder" items left less than the chunk-size:

public IEnumerable<IEnumerable<T>> EatWhile<T>(IEnumerable<T> list, int bitesize)
{
     while (list.Any())
      {
         yield return list.Take(bitesize);
         list = list.Skip(bitesize);
      }

      if (list.Any()) yield return list;
}

There are probably better ways to do this :)
Matt T Heffron 28-Sep-15 20:56pm    
This is incredibly inefficient!!!
See my article: Considerations on Efficient use of LINQ Extension Methods
BillWoodruff 28-Sep-15 20:57pm    
Okay, I will study your article ! fyi: my preference is to just use straight ahead for-loop processing, but I posted that example because I thought that's what you were trying to do in you solution.
Matt T Heffron 28-Sep-15 21:28pm    
I was just "generalizing" your solution.
It could get kind of ugly if OP wanted 20 rows per document (or a parameter to set the number of rows/document)!
Of course, then an inner loop could be used, but it isn't really necessary! But those still need to know how many are actually being processed. My solution doesn't.
BillWoodruff 28-Sep-15 21:37pm    
I think the more fun we have the better off the OP :)

cheers, Bill

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900