2017-07-17 58 views
0

我在如何解决我的问题与我的datagridview打印预览挣扎。这是整个代码:在vb.net中打印Datagridview数据

Imports System.Data.SqlClient 

Public Class FrmPrintClassSchedule 

Dim strConn As String = "Data Source=Jansen;Initial Catalog=SLCBRegistrarDB;Integrated Security=True" 
Dim sqlCon As SqlConnection = New SqlConnection(strConn) 
Dim CMD As SqlCommand 
Dim Adapter As SqlDataAdapter 
Dim Reader As SqlDataReader 
Dim DT As DataTable 

Private Sub LoadCLASSSCHEDULES() 
    sqlCon = New SqlConnection("Data Source=Jansen;Initial Catalog=SLCBRegistrarDB;Integrated Security=True") 
    sqlCon.Open() 
    CMD = sqlCon.CreateCommand 
    CMD.CommandText = ("SELECT [Class Schedule LINE].SchedID, ListofSubjects.[Course No.], ListofSubjects.[Descriptive Title],Curriculum.[Lab.]+ Curriculum.[Lec.] , UtlyTIMETable.[FROM Time]+'-'+ UtlyTIMETable.[TO Time]+' '+ UtlyDAY.Day+' '+ UtlyRoom.Building+' '+UtlyRoom.[Room No.], UtlyInstructor.[Last Name]+', '+ UtlyInstructor.[First Name], YearLevel.[Year Level], CourseOfferings.Course, CourseOfferings.[Degree Course], ListCurricularYear.[Curriculum Year], [Class Schedule Status].[Class Schedule Status] " & 
         "FROM [Class Schedule LINE] INNER JOIN Curriculum ON [Class Schedule LINE].[Subject Code] = Curriculum.[Subject Code] INNER JOIN CourseOfferings ON Curriculum.CourseID = CourseOfferings.CourseID INNER JOIN ListofSubjects ON Curriculum.SubjectID = ListofSubjects.SubjectID INNER JOIN Section ON [Class Schedule LINE].Section = Section.SectionID INNER JOIN UtlyDAY ON [Class Schedule LINE].DayID = UtlyDAY.DayID INNER JOIN UtlyInstructor ON [Class Schedule LINE].InstructorID = UtlyInstructor.IntructorID INNER JOIN UtlyRoom ON [Class Schedule LINE].RoomID = UtlyRoom.RoomID INNER JOIN UtlyTIMETable ON [Class Schedule LINE].TimeID = UtlyTIMETable.TimeID INNER JOIN YearLevel ON Curriculum.YearLevelID = YearLevel.[Year Level] INNER JOIN ListCurricularYear ON Curriculum.CurriculumID = ListCurricularYear.CurriculumID INNER JOIN [Class Schedule Status] ON [Class Schedule LINE].StatusofSchedule = [Class Schedule Status].StatusofClassScheduleID " & 
         "WHERE (Section.Section = '" & cmbSection.Text & "') AND (YearLevel.[Year Level] = '" & txtYearLevel.Text & "') AND (CourseOfferings.Course = '" & cmbCOURSE.Text & "') AND (CourseOfferings.[Degree Course] = '" & cmbDegreeTitle.Text & "') AND (ListCurricularYear.[Curriculum Year] = '" & cmbCurricularyear.Text & "') AND ([Class Schedule Status].[Class Schedule Status] = 'Active')") 
    Reader = CMD.ExecuteReader() 
    If Reader.HasRows Then 
     Dim DT As New DataTable 
     DT.Load(Reader) 
     dgvPrintClassSchedule.DataSource = DT 

     dgvPrintClassSchedule.Columns(6).Visible = False 
     dgvPrintClassSchedule.Columns(7).Visible = False 
     dgvPrintClassSchedule.Columns(8).Visible = False 
     dgvPrintClassSchedule.Columns(9).Visible = False 
     dgvPrintClassSchedule.Columns(10).Visible = False 

     dgvPrintClassSchedule.RowHeadersWidth = 25 
     dgvPrintClassSchedule.Columns(0).Width = 75 
     dgvPrintClassSchedule.Columns(0).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter 
     dgvPrintClassSchedule.Columns(0).HeaderText = "Schedule No." 
     dgvPrintClassSchedule.Columns(3).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter 
     dgvPrintClassSchedule.Columns(3).HeaderText = "Units" 
     dgvPrintClassSchedule.Columns(4).HeaderText = "Schedule and Room Assignment" 
     dgvPrintClassSchedule.Columns(5).HeaderText = "Instructor" 
     dgvPrintClassSchedule.Columns(1).Width = 100 
     dgvPrintClassSchedule.Columns(3).Width = 50 
     dgvPrintClassSchedule.Columns(2).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill 
     dgvPrintClassSchedule.Columns(4).Width = 200 
     dgvPrintClassSchedule.Columns(5).Width = 150 
     dgvPrintClassSchedule.Columns(5).DefaultCellStyle.Font = New Font("Calibri", 9) 

    End If 
    Reader.Close() 
    sqlCon.Close() 
End Sub 

Private Sub LoadCURRICULUM() 
    Try 
     sqlCon.Open() 
     Dim QUERY As String 
     QUERY = "SELECT * FROM ListCurricularYear" 
     CMD = New SqlCommand(QUERY, sqlCon) 
     Reader = CMD.ExecuteReader 
     While Reader.Read 
      cmbCurricularyear.Items.Add(Reader.GetString(1)) 
     End While 
     sqlCon.Close() 
    Catch ex As Exception 
     MessageBox.Show(ex.Message) 
    End Try 
End Sub 

Private Sub LoadCOURSES() 
    Try 
     sqlCon.Open() 
     Dim QUERY As String 
     QUERY = "SELECT Course, [Degree Course] FROM CourseOfferings" 
     CMD = New SqlCommand(QUERY, sqlCon) 
     Reader = CMD.ExecuteReader 
     While Reader.Read 
      cmbCOURSE.Items.Add(Reader.GetString(0)) 
      cmbDegreeTitle.Items.Add(Reader.GetString(1)) 
     End While 
     sqlCon.Close() 
    Catch ex As Exception 
     MessageBox.Show(ex.Message) 
    End Try 
End Sub 

Private Sub cmbCOURSE_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbCOURSE.SelectedIndexChanged 
    Try 
     sqlCon.Open() 
     Dim QUERY As String 
     QUERY = "SELECT * FROM CourseOfferings WHERE Course='" & cmbCOURSE.Text & "'" 
     CMD = New SqlCommand(QUERY, sqlCon) 
     Reader = CMD.ExecuteReader 
     While Reader.Read 
      cmbDegreeTitle.Text = Reader.GetString(2) 
     End While 
     sqlCon.Close() 
    Catch ex As Exception 
     MessageBox.Show(ex.Message) 
    End Try 
End Sub 

Private Sub cmbSection_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbSection.SelectedIndexChanged 
    LoadCLASSSCHEDULES() 
End Sub 

''' <summary> 
''' structire to hold printed page details 
''' </summary> 
''' <remarks></remarks> 
Private Structure pageDetails 
    Dim columns As Integer 
    Dim rows As Integer 
    Dim startCol As Integer 
    Dim startRow As Integer 
End Structure 
''' <summary> 
''' dictionary to hold printed page details, with index key 
''' </summary> 
''' <remarks></remarks> 
Private pages As Dictionary(Of Integer, pageDetails) 

Dim maxPagesWide As Integer 
Dim maxPagesTall As Integer 

''' <summary> 
''' this just loads some text values into the dgv 
''' </summary> 
''' <param name="sender"></param> 
''' <param name="e"></param> 
''' <remarks></remarks> 
Private Sub FrmPrintClassSchedule_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
    'LoadCLASSSCHEDULES() 
    LoadCURRICULUM() 
    LoadCOURSES() 



    'dgvPrintClassSchedule.RowHeadersWidth = CInt(dgvPrintClassSchedule.RowHeadersWidth * 1.35) 
    'For r As Integer = 1 To 100 
    'Dim y As Integer = r 
    'Dim fmt As String = "R{0}C{1}" 
    'dgvPrintClassSchedule.Rows.Add() 
    'dgvPrintClassSchedule.Rows(r - 1).SetValues(Enumerable.Range(1, 10).Select(Function(x) String.Format(fmt, y, x)).ToArray) 
    'dgvPrintClassSchedule.Rows(r - 1).HeaderCell.Value = r.ToString 
    'Next 
End Sub 

''' <summary> 
''' shows a PrintPreviewDialog 
''' </summary> 
''' <param name="sender"></param> 
''' <param name="e"></param> 
''' <remarks></remarks> 
Private Sub btnPreview_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrintPreview.Click 
    Dim ppd As New PrintPreviewDialog 
    ppd.Document = PrintDocument1 
    ppd.WindowState = FormWindowState.Maximized 
    ppd.ShowDialog() 
End Sub 

''' <summary> 
''' starts print job 
''' </summary> 
''' <param name="sender"></param> 
''' <param name="e"></param> 
''' <remarks></remarks> 
Private Sub btnPrint_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnPrint.Click 
    PrintDocument1.Print() 
End Sub 

''' <summary> 
''' the majority of this Sub is calculating printed page ranges 
''' </summary> 
''' <param name="sender"></param> 
''' <param name="e"></param> 
''' <remarks></remarks> 
Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocument1.BeginPrint 
    ''this removes the printed page margins 
    PrintDocument1.OriginAtMargins = True 
    PrintDocument1.DefaultPageSettings.Margins = New Drawing.Printing.Margins(0, 0, 0, 0) 

    pages = New Dictionary(Of Integer, pageDetails) 

    Dim maxWidth As Integer = CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width) - 40 
    Dim maxHeight As Integer = CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Height) - 40 + Label1.Height 

    Dim pageCounter As Integer = 0 
    pages.Add(pageCounter, New pageDetails) 

    Dim columnCounter As Integer = 0 

    Dim columnSum As Integer = dgvPrintClassSchedule.RowHeadersWidth 

    For c As Integer = 0 To dgvPrintClassSchedule.Columns.Count - 1 
     If columnSum + dgvPrintClassSchedule.Columns(c).Width < maxWidth Then 
      columnSum += dgvPrintClassSchedule.Columns(c).Width 
      columnCounter += 1 
     Else 
      pages(pageCounter) = New pageDetails With {.columns = columnCounter, .rows = 0, .startCol = pages(pageCounter).startCol} 
      columnSum = dgvPrintClassSchedule.RowHeadersWidth + dgvPrintClassSchedule.Columns(c).Width 
      columnCounter = 1 
      pageCounter += 1 
      pages.Add(pageCounter, New pageDetails With {.startCol = c}) 
     End If 
     If c = dgvPrintClassSchedule.Columns.Count - 1 Then 
      If pages(pageCounter).columns = 0 Then 
       pages(pageCounter) = New pageDetails With {.columns = columnCounter, .rows = 0, .startCol = pages(pageCounter).startCol} 
      End If 
     End If 
    Next 

    maxPagesWide = pages.Keys.Max + 1 

    pageCounter = 0 

    Dim rowCounter As Integer = 0 

    Dim rowSum As Integer = dgvPrintClassSchedule.ColumnHeadersHeight 

    For r As Integer = 0 To dgvPrintClassSchedule.Rows.Count - 2 
     If rowSum + dgvPrintClassSchedule.Rows(r).Height < maxHeight Then 
      rowSum += dgvPrintClassSchedule.Rows(r).Height 
      rowCounter += 1 
     Else 
      pages(pageCounter) = New pageDetails With {.columns = pages(pageCounter).columns, .rows = rowCounter, .startCol = pages(pageCounter).startCol, .startRow = pages(pageCounter).startRow} 
      For x As Integer = 1 To maxPagesWide - 1 
       pages(pageCounter + x) = New pageDetails With {.columns = pages(pageCounter + x).columns, .rows = rowCounter, .startCol = pages(pageCounter + x).startCol, .startRow = pages(pageCounter).startRow} 
      Next 

      pageCounter += maxPagesWide 
      For x As Integer = 0 To maxPagesWide - 1 
       pages.Add(pageCounter + x, New pageDetails With {.columns = pages(x).columns, .rows = 0, .startCol = pages(x).startCol, .startRow = r}) 
      Next 

      rowSum = dgvPrintClassSchedule.ColumnHeadersHeight + dgvPrintClassSchedule.Rows(r).Height 
      rowCounter = 1 
     End If 
     If r = dgvPrintClassSchedule.Rows.Count - 2 Then 
      For x As Integer = 0 To maxPagesWide - 1 
       If pages(pageCounter + x).rows = 0 Then 
        pages(pageCounter + x) = New pageDetails With {.columns = pages(pageCounter + x).columns, .rows = rowCounter, .startCol = pages(pageCounter + x).startCol, .startRow = pages(pageCounter + x).startRow} 
       End If 
      Next 
     End If 
    Next 

    maxPagesTall = pages.Count \ maxPagesWide 

End Sub 

''' <summary> 
''' this is the actual printing routine. 
''' using the pagedetails i calculated earlier, it prints a title, 
''' + as much of the datagridview as will fit on 1 page, then moves to the next page. 
''' this is setup to be dynamic. try resizing the dgv columns or rows 
''' </summary> 
''' <param name="sender"></param> 
''' <param name="e"></param> 
''' <remarks></remarks> 
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage 
    Dim rect As New Rectangle(20, 20, CInt(PrintDocument1.DefaultPageSettings.PrintableArea.Width), Label1.Height) 
    Dim sf As New StringFormat 
    sf.Alignment = StringAlignment.Center 
    sf.LineAlignment = StringAlignment.Center 

    e.Graphics.DrawString(Label1.Text, Label1.Font, Brushes.Black, rect, sf) 

    sf.Alignment = StringAlignment.Near 

    Dim startX As Integer = 50 
    Dim startY As Integer = rect.Bottom 

    Static startPage As Integer = 0 

    For p As Integer = startPage To pages.Count - 1 
     Dim cell As New Rectangle(startX, startY, dgvPrintClassSchedule.RowHeadersWidth, dgvPrintClassSchedule.ColumnHeadersHeight) 
     e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell) 
     e.Graphics.DrawRectangle(Pens.Black, cell) 

     startY += dgvPrintClassSchedule.ColumnHeadersHeight 

     For r As Integer = pages(p).startRow To pages(p).startRow + pages(p).rows - 1 
      cell = New Rectangle(startX, startY, dgvPrintClassSchedule.RowHeadersWidth, dgvPrintClassSchedule.Rows(r).Height) 
      e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell) 
      e.Graphics.DrawRectangle(Pens.Black, cell) 
      e.Graphics.DrawString(dgvPrintClassSchedule.Rows(r).HeaderCell.Value.ToString, dgvPrintClassSchedule.Font, Brushes.Black, cell, sf) 
      startY += dgvPrintClassSchedule.Rows(r).Height 
     Next 

     startX += cell.Width 
     startY = rect.Bottom 

     For c As Integer = pages(p).startCol To pages(p).startCol + pages(p).columns - 1 
      cell = New Rectangle(startX, startY, dgvPrintClassSchedule.Columns(c).Width, dgvPrintClassSchedule.ColumnHeadersHeight) 
      e.Graphics.FillRectangle(New SolidBrush(SystemColors.ControlLight), cell) 
      e.Graphics.DrawRectangle(Pens.Black, cell) 
      e.Graphics.DrawString(dgvPrintClassSchedule.Columns(c).HeaderCell.Value.ToString, dgvPrintClassSchedule.Font, Brushes.Black, cell, sf) 
      startX += dgvPrintClassSchedule.Columns(c).Width 
     Next 

     startY = rect.Bottom + dgvPrintClassSchedule.ColumnHeadersHeight 

     For r As Integer = pages(p).startRow To pages(p).startRow + pages(p).rows - 1 
      startX = 50 + dgvPrintClassSchedule.RowHeadersWidth 
      For c As Integer = pages(p).startCol To pages(p).startCol + pages(p).columns - 1 
       cell = New Rectangle(startX, startY, dgvPrintClassSchedule.Columns(c).Width, dgvPrintClassSchedule.Rows(r).Height) 
       e.Graphics.DrawRectangle(Pens.Black, cell) 
       e.Graphics.DrawString(dgvPrintClassSchedule(c, r).Value.ToString, dgvPrintClassSchedule.Font, Brushes.Black, cell, sf) 
       startX += dgvPrintClassSchedule.Columns(c).Width 
      Next 
      startY += dgvPrintClassSchedule.Rows(r).Height 
     Next 

     If p <> pages.Count - 1 Then 
      startPage = p + 1 
      e.HasMorePages = True 
      Return 
     Else 
      startPage = 0 
     End If 

    Next 

End Sub 

End Class 

数据在DataGridView被加载后,然后当我点击打印预览按钮,它应该是工作,但这个错误永远是:

对象引用不设置到对象的实例。 错误代码:

e.Graphics.DrawString(dgvPrintClassSchedule.Rows(R).HeaderCell.Value.ToString,dgvPrintClassSchedule.Font,Brushes.Black,细胞,SF)

我不能找到一种方法关于如何摆脱这个错误..请帮助..谢谢

+0

请阅读[问]并参加[旅游]。我们不需要你的整个代码,只是足以证明错误和背景 – Plutonix

回答

0

您需要确保dgvPrintClassSchedule.Rows(r).HeaderCell在使用该值之前不为空。

尝试e.Graphics.DrawString( “测试”,dgvPrintClassSchedule.Font,Brushes.Black,细胞,SF)

你仍然可以看到异常?

是否定义了dgvPrintClassSchedule.Font?

+0

ow是的!感谢man..that这就是我所说的..哦抱歉的反馈迟了。当我能够发布我的问题时已经是晚上11点半了。任何方式非常感谢很多.. – Diaval

+0

是他们的任何方式,我会打印只有在datagridview使用我上面提供的代码的特定列? – Diaval