C1 Community
ComponentOne Community is a free source for developers and help authors to collaborate and communicate.

Repeating page headers in the Document Object

rated by 0 users
This post has 4 Replies | 2 Followers

Not Ranked
Posts 7
Jsmith-EASE Posted: Tue, Jun 16 2009 6:10 PM

Hi

I am using the PrintDocument object to generate the report and the report has 4 pages.

The first page has 3 headers( namely 1,2,3) and in the remaining pages, I would like to display only 1, 3 headers. How do I do that? Do you have any samples?

I am trying to use the "PageAdded" in the Document object to add the headers and getting the "Collection was modified; enumeration operation may not execute" message.

I have also created a sample Windows application to replicate this behaviour. I have added the "C1PrintDocument" and "C1PrintPreviewControl" controls in the form. Here is the form code. 

Imports C1.C1Preview

Public Class Form2

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Me.Close()

End Sub

Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

GeneratePages()

End Sub

Private Sub GeneratePages()Dim intK As Int16 = 0

AddHeader1()

AddHeader2()

AddHeader3()

Dim objTable As New RenderTable()

For intK = 1 To 200

objTable.Cells(intK, 0).Text = "Line " & intK

Next

C1PrintDocument1.Body.Children.Add(objTable)

objTable = Nothing

C1PrintDocument1.Reflow()

End Sub

Private Sub AddHeader1()

Dim objTable As New RenderTable()

objTable.Cells(0, 0).Text = "header 1"

objTable.Style.BackColor = Color.LightGray

C1PrintDocument1.Body.Children.Add(objTable)

objTable = Nothing

End Sub

Private Sub AddHeader2()

Dim objTable As New RenderTable()

objTable.Cells(0, 0).Text = "header 2"

objTable.Style.BackColor = Color.LightCoral

C1PrintDocument1.Body.Children.Add(objTable)

objTable = Nothing

End Sub

Private Sub AddHeader3()

Dim objTable As New RenderTable()

objTable.Cells(0, 0).Text = "header 3"

objTable.Style.BackColor = Color.LightYellow

C1PrintDocument1.Body.Children.Add(objTable)

objTable = Nothing

End Sub

Private Sub C1PrintDocument1_PageAdded(ByVal sender As C1.C1Preview.C1PrintDocument, ByVal e As C1.C1Preview.PageEventArgs) Handles C1PrintDocument1.PageAdded

'If e.Page.PageNo > 1 Then

' AddHeader1()

' AddHeader3()

'End If

End Sub

End Class

 

In this report, how can I add the header1 and header3 in pages 2, 3 and 4. Any help would be appreciated.

 

Regards, Karthik

Top 10 Contributor
Posts 1,394
C1_Dima replied on Wed, Jun 17 2009 3:22 PM

You are not approaching this correctly. C1PrintDocument has built-in mechanism for page headers and footers, and that is what should be used in this case.

Here's the modified version of your GeneratePages that does what you need, hope it helps:

 

    Private Sub GeneratePages()
        Dim intK As Int16 = 0

        Dim headerFirstPage As New RenderTable
        headerFirstPage.Cells(0, 0).Text = "header 1"
        headerFirstPage.Cells(0, 0).Style.BackColor = Color.LightGray
        headerFirstPage.Cells(1, 0).Text = "header 2"
        headerFirstPage.Cells(1, 0).Style.BackColor = Color.LightCoral
        headerFirstPage.Cells(2, 0).Text = "header 3"
        headerFirstPage.Cells(2, 0).Style.BackColor = Color.LightYellow

        Dim headerDefault As RenderTable = headerFirstPage.Clone
        headerDefault.Rows.Delete(1)

        C1PrintDocument1.PageLayouts.FirstPage = New PageLayout
        C1PrintDocument1.PageLayouts.FirstPage.PageHeader = headerFirstPage

        C1PrintDocument1.PageLayouts.Default = New PageLayout
        C1PrintDocument1.PageLayouts.Default.PageHeader = headerDefault

        Dim objTable As New RenderTable()

        For intK = 1 To 200
            objTable.Cells(intK, 0).Text = "Line " & intK
        Next

        C1PrintDocument1.Body.Children.Add(objTable)

        objTable = Nothing

        C1PrintDocument1.Reflow()
    End Sub
 

Cheers, Dima.
Not Ranked
Posts 7

Dima,

Thanks for the quick response. I have one more question regarding the page headers.

Based on the sample code, I can set the page headers only for first page, last page, odd or even pages. Is there a way, I can manually set the page headers for every page.

For example, the "Employees" report includes the following sub reports.

 1. List of all employees (summary page)

After printing the summary page, we need to print the sub reports by employee. The sub-reports include the following

2. Project history for the employee (list of projects worked by the employee)

3. Technical expertise for the employee

4. Educational qualification and training

The sub reports 2,3,4 prints for each employee in a separte pages and the sub report may exceed more than one page. The subreports include different headers also require sub report header in every page.

How do we accomplish this format?. Any idea or direction would be greatly appreciated.

 Regards, Karthik

Top 10 Contributor
Posts 1,394
C1_Dima replied on Thu, Jun 18 2009 8:49 AM

You can use the RenderObject's LayoutChangeBefore and LayoutChangeAfter properties to change page layout before or after any object in your document. Those properties are of the abstract type LayoutChangeBase, which has several derived types determining whether a new page or column is started when that layout change is applied (such as LayoutChangeNewPage, which inserts a page break). If you implement your sub-report as a separate render object, e.g. as a RenderTable, you can assign a LayoutChangeNewPage to its LayoutChangeBefore property, set Nested on that layout change to True so that the previous layout is restored when the sub-report returns, and specify any layout properties for the sub-report - including of course page headers/footers. Below is a small example:

    Private Sub GeneratePages()

        Dim intK As Int16 = 0

        Dim headerFirstPage As New RenderTable
        headerFirstPage.Cells(0, 0).Text = "header 1"
        headerFirstPage.Cells(0, 0).Style.BackColor = Color.LightGray
        headerFirstPage.Cells(1, 0).Text = "header 2"
        headerFirstPage.Cells(1, 0).Style.BackColor = Color.LightCoral
        headerFirstPage.Cells(2, 0).Text = "header 3"
        headerFirstPage.Cells(2, 0).Style.BackColor = Color.LightYellow

        Dim headerDefault As RenderTable = headerFirstPage.Clone
        headerDefault.Rows.Delete(1)

        C1PrintDocument1.PageLayouts.FirstPage = New PageLayout
        C1PrintDocument1.PageLayouts.FirstPage.PageHeader = headerFirstPage

        C1PrintDocument1.PageLayouts.Default = New PageLayout
        C1PrintDocument1.PageLayouts.Default.PageHeader = headerDefault

        Dim objTable As New RenderTable()

        For intK = 1 To 200
            objTable.Cells(intK, 0).Text = "Line " & intK
        Next

        C1PrintDocument1.Body.Children.Add(objTable)

        Dim t2 As New RenderTable
        For intK = 0 To 100
            t2.Cells(intK, 0).Text = String.Format("Table 2 row {0}", intK)
        Next
        Dim lcnp As New LayoutChangeNewPage
        t2.LayoutChangeBefore = lcnp
        lcnp.Nested = True
        lcnp.PageLayout = New PageLayout
        lcnp.PageLayout.PageHeader = New RenderText("NESTED PAGE HEADER")
        lcnp.PageLayout.PageFooter = New RenderText("NESTED PAGE FOOTER")
        C1PrintDocument1.Body.Children.Add(t2)

        C1PrintDocument1.Body.Children.Add(New RenderText("Last Render object"))

        C1PrintDocument1.Reflow()
    End Sub
 

As an alternative, you can set AllowNonReflowableDocs to True on your C1PrintDocument, and then use its PageConfigure event to specify page layout for each page in code, e.g.:

  C1PrintDocument1.AllowNonReflowableDocs = True ' Needed to use PageConfigure event

...

    Private Sub C1PrintDocument1_PageConfigure(ByVal sender As C1.C1Preview.C1PrintDocument, ByVal e As C1.C1Preview.PageConfigureEventArgs) Handles C1PrintDocument1.PageConfigure
        If e.Page.PageNo = 3 Then
            e.PageLayout = New PageLayout
            e.PageLayout.PageHeader = New RenderText("Page header on page 3")
        End If
    End Sub
 

But the first approach (using LayoutChange* properties) is better IMHO. Hope this helps.

 

Cheers, Dima.
Not Ranked
Posts 7

Dima,

Thanks for both solutions and that works like a charm.

Appreciate your help and quick response.

Regards, Karthik 

 

Page 1 of 1 (5 items) | RSS
Contact ComponentOne: 1.800.858.2739 ©1987-2010 ComponentOne LLC All Rights Reserved.