none
使用 SqlDataReader 搭配 hasMorePages 無法正常跳頁 RRS feed

  • 問題

  •  

    試了好久,要不就是不會跳頁,要不就是第二頁的資料跟第一頁的資料一模一樣,

    底下我把我的程式簡化貼上來,可不可以麻煩幫我看一下,到底是那裡出了問題呢?

    非常感激,我實在是試不出來:

     

    (我是 VB .net 的新手,寫法有點怪怪的,程式碼也沒有什麼結構,請多多包含)

     

        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

            Dim cmd1 As New SqlCommand
            cmd1.CommandText = "select xxx, yyy, zzz from someTable"
            cmd1.Connection = CON.CN
            If cmd1.Connection.State = ConnectionState.Open Then
                cmd1.Connection.Close()
            End If
            cmd1.Connection.Open()
            Using dr1 As SqlDataReader = cmd1.ExecuteReader

     

                While (dr1.Read())

                    '====== 列印相關表頭 開始=====
                    '如果餘數是 1 的時候(每頁的第一筆資料)才印相關表頭
                    If ((countt + 1 Mod 10) = 1) Then
                        '表頭
                        e.Graphics.DrawString(title, fontTitle, Brushes.Black, 500, 5)
                    End If
                    '====== 列印相關表頭 結束=====


                    '====== 列印細項內容 開始=====
                    For p As Integer = 0 To fieldCount - 1
                        e.Graphics.DrawString(TOOL.getArea(printString(p)), fontContent, Brushes.Black, tabControlC(p), (60 + countt * lineD))
                    Next

                    '====================  列印表尾 開始 =====================
                    '每頁的最後一筆之後,加印表尾
                    If (countt Mod 10) = 0 Then
                        e.Graphics.DrawString(footer, fontContent, Brushes.Black, 590, 760)
                    End If

                    '====================  列印表尾 結束 =====================

     

                    countt += 1
                    totalRecords -= 1

     

                    '當總筆數歸零時,表示沒資料了,列印完最後一次表尾之後,就停止列印
                    If totalRecords = 0 Then
                        '分隔線
                        For k As Integer = 3 To lineLength
                            e.Graphics.DrawString(footer, fontContent, Brushes.Black, 590, 760)
                        Next
                        e.HasMorePages = False
                        Exit Sub
                    else
                        e.HasMorePages = True
                    End If


                End While
            End Using
        End Sub

     

    我只有十四筆資料,一頁限定只列印十筆,所以第二頁影該要列印 11-14 的資料,但是以上這樣執行的結果,

    會有表頭表尾的列印,但是第十一筆印完,就不會跳到第二頁,請幫幫我,謝謝!!

    2008年9月22日 上午 05:38

解答

  •  

    本來的程式有加這些判斷,只是簡化之後,被我給刪了。

     

    微軟工程師有回我了,遇到我這個小白問他這個問題,大概讓他有點啼笑皆非,

    畢竟我不是本科系,也不是專搞程式的,所以對我來說困難了許多。

     

    以下是我收到回覆之後,簡化後可執行的程式碼片段了。

     

    這次為什麼堅持要用這種方式來列印,實在是因為每筆資料的最前面要有一張圖,

    這圖是一些簡單的線條圖形,接著要去資料庫抓線條的尺寸,以及對應的座標,

    最後換算好之後,全部標示出來,而圖形的後面才會接相關的文字欄位,

     

    有這方面需要的人,應該是可以把它簡化得更簡單一些,以後不想用 Crystal Report

    或 ActiveReport之類的工具的話,要把資料庫裡的資料讀出來列印,只要套用下面的

    模式就好了。

     

    ===== 程式碼及說明開始 =====

    第一個部分,按下列印之後

    (把 SQL 另外獨立出來,填到一個 DataAdapter)

     

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

            Dim qString As String = "select  someFileds from someTable"
            Dim cmd As New SqlCommand(qString)
            Dim da As New SqlDataAdapter(qString, CONN)
            da.Fill(tb)

     

    '昨天發現不足一頁時會有問題,以下綠色的字是改過的部分

                    If tb.Rows.Count > 0 Then
                        tb.Rows.Clear()
                    End If

                    '起始索引, 結束索引初始化
                    startidx = 1
                    If tb.Rows.Count > linesPerPage Then
                        endidx = linesPerPage '我把每頁的筆數獨立出來了
                    Else
                        endidx = tb.Rows.Count
                    End If

     

            '計算總頁數
            If tb.Rows.Count Mod linesPerPage <> 0 Then
                totalPages = (tb.Rows.Count \ linesPerPage ) + 1
            Else
                totalPages = (tb.Rows.Count \ linesPerPage )
            End If
            PrintDocument1.Print()
        End Sub

     

    第二個部分,PrintDocument

     

        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

            '計算目前所在頁數
            Dim countt As Integer = 0

    'countt 這個是我自己加進來,計算每頁每筆之間的行距用的,因為剛剛在測的時候,

    如果用 startidx Mod linesPerPage 來計算,第二頁的第一筆的位置會跑掉,所以另外設定一個。


            Dim currentpage As Integer
            If (endidx Mod 10 <> 0) Then
                currentpage = (endidx \ linesPerPage ) + 1
            Else
                currentpage = endidx \ linesPerPage 
            End If

            '開始資料讀取迴圈,每頁最多十筆資料
            While startidx <= endidx
                '第一筆印header
                If (startidx Mod linesPerPage = 1) Then
                    '這裡可以放表頭
                End If


                '列印細項內容


      '列印表尾

      '每頁的最後一筆之後,加印表尾
      If (startidx Mod linesPerPage = 0) Then

                      '這裡可以放表尾
                End If

                startidx += 1
                countt += 1

            End While

     

            '判斷換頁
            If endidx < tb.Rows.Count Then
                e.HasMorePages = True
            Else
                e.HasMorePages = False
            End If

     

            '若最後一頁不滿10筆則結束索引為最後一筆資料的索引
            If currentpage < totalPages Then
                startidx = currentpage * linesPerPage + 1
                If (currentpage + 1) * linesPerPage >= tb.Rows.Count Then
                    endidx = tb.Rows.Count
                Else
                    endidx = (currentpage + 1) * linesPerPage 
                End If

            End If

        End Sub

    2008年9月25日 上午 03:28

所有回覆

  • 你觀念錯了,HasMorePages 不是放在回圈內用的。

     

    搜尋既有討論即有說明:

    http://forums.microsoft.com/MSDN-CHT/Search/Search.aspx?words=HasMorePages&localechoice=31748&SiteID=14&searchscope=allforums

     

    2008年9月22日 下午 12:24
  • 其實我也是看完搜尋的文章之後,才來貼這個問題的,

    只是看到最後,還是沒有解答,幾乎都是帶過,也因此

    我得到了一個結論,就是:這個解答是要錢的。

     

    觀念正確也不會來這裡問了,因為踹了一個多禮拜,從不會跳頁,

    到會跳頁了資料卻不正確,現在再變成又不跳頁了,哈!

     

    PrintDocument 真是一個不好理解的東西

     

    既然得不到答案,我想還是乖乖的付錢好了。

    2008年9月23日 上午 02:14
  • 你要去付錢我是不反對啦...

     

    不過我不知道你眼睛看到哪:

    回覆:請問關於printDocument->print的問題。  

    Code Snippet

    HasMorePages = true;

    並不會分頁或換頁。

    真正換頁是在 PringPage 事件結束後。

     

    HasMorePages = true;

    只是告訴 PrintDocument 物件還要再一次回呼 PrintPage 事件。

     

    線上手冊即有簡單的範例,包含預覽列印可參考。

     

    回覆:報表的 e.HasMorePages 問題   

    Code Snippet

    列印本身是回呼的方式來畫圖,.Net 在上層幫你包好 Job 的處理,所以 .Net 並不知道你一頁印完沒。

     

    當你告知 .Net 說還有更多的頁面時,當你目前這個事件結束後,.Net 才知道要再回呼這個事件繼續列印,並把先前已經輸出的頁面送往印表機。

     

    所以沒特別的,只是讓控制項知道還要再回呼事件繼續列印。

     

     

     

    你還可以仔細看其它搜尋的結果,幾乎都跟你一樣,把 HasMorePages 當方法,而非當屬性。

     

    HasMorePages 並非是執行分頁的方法,而是告知還需要回呼,所以你在 PringPage 裡面不該用以頁為單位的迴圈。

    2008年9月23日 上午 03:56
  • 真的非常謝謝你的回覆,真的,在此致上深深的感激。

     

    我想癥結出在我的理解力太差,太依賴要有直接的解決方法,

    您貼的片段我真的有看過,也試圖去理解它,但是說真的

    我體會不來,實在是太駑頓了,是我不好。

     

    我再多看看文章,謝謝!

     

    我還是貼一下我最新改好的樣子:

     

        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

            Static totalRecords = 14

            Static countt As Integer = 0

            cmd1.CommandText = "select  some columns from some table"
            cmd1.Connection = CON.CN
            cmd1.Connection.Open()
            Dim dr1 As SqlDataReader = cmd1.ExecuteReader

     

            While (dr1.Read())

                '列印相關表頭
                '列印細項內容
                '列印表尾

            End While

     

            totalRecords = totalRecords - 1

     

            '判斷是否跳頁
            If totalRecords = 0 Then
                e.HasMorePages = False
            Else
                e.HasMorePages = True
            End If

        End Sub

     

    我的資料只有十四筆,執行的結果,會印十四頁,每頁除了表頭表尾之外,細項印了十一筆。

    2008年9月23日 上午 05:08
  • 把你 SQL 查詢跟列印程式碼分開來,不然你就去看看 SQL 分頁查詢的語法怎樣下。

     

    你要印 1 頁 11 筆,就應該明確的把這個判斷敘述寫出來。請問你寫在哪?

     

    沒看到你有用 xxx Mod 11 的判斷敘述存在。

    2008年9月23日 上午 05:25
  •  

    本來的程式有加這些判斷,只是簡化之後,被我給刪了。

     

    微軟工程師有回我了,遇到我這個小白問他這個問題,大概讓他有點啼笑皆非,

    畢竟我不是本科系,也不是專搞程式的,所以對我來說困難了許多。

     

    以下是我收到回覆之後,簡化後可執行的程式碼片段了。

     

    這次為什麼堅持要用這種方式來列印,實在是因為每筆資料的最前面要有一張圖,

    這圖是一些簡單的線條圖形,接著要去資料庫抓線條的尺寸,以及對應的座標,

    最後換算好之後,全部標示出來,而圖形的後面才會接相關的文字欄位,

     

    有這方面需要的人,應該是可以把它簡化得更簡單一些,以後不想用 Crystal Report

    或 ActiveReport之類的工具的話,要把資料庫裡的資料讀出來列印,只要套用下面的

    模式就好了。

     

    ===== 程式碼及說明開始 =====

    第一個部分,按下列印之後

    (把 SQL 另外獨立出來,填到一個 DataAdapter)

     

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

            Dim qString As String = "select  someFileds from someTable"
            Dim cmd As New SqlCommand(qString)
            Dim da As New SqlDataAdapter(qString, CONN)
            da.Fill(tb)

     

    '昨天發現不足一頁時會有問題,以下綠色的字是改過的部分

                    If tb.Rows.Count > 0 Then
                        tb.Rows.Clear()
                    End If

                    '起始索引, 結束索引初始化
                    startidx = 1
                    If tb.Rows.Count > linesPerPage Then
                        endidx = linesPerPage '我把每頁的筆數獨立出來了
                    Else
                        endidx = tb.Rows.Count
                    End If

     

            '計算總頁數
            If tb.Rows.Count Mod linesPerPage <> 0 Then
                totalPages = (tb.Rows.Count \ linesPerPage ) + 1
            Else
                totalPages = (tb.Rows.Count \ linesPerPage )
            End If
            PrintDocument1.Print()
        End Sub

     

    第二個部分,PrintDocument

     

        Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

            '計算目前所在頁數
            Dim countt As Integer = 0

    'countt 這個是我自己加進來,計算每頁每筆之間的行距用的,因為剛剛在測的時候,

    如果用 startidx Mod linesPerPage 來計算,第二頁的第一筆的位置會跑掉,所以另外設定一個。


            Dim currentpage As Integer
            If (endidx Mod 10 <> 0) Then
                currentpage = (endidx \ linesPerPage ) + 1
            Else
                currentpage = endidx \ linesPerPage 
            End If

            '開始資料讀取迴圈,每頁最多十筆資料
            While startidx <= endidx
                '第一筆印header
                If (startidx Mod linesPerPage = 1) Then
                    '這裡可以放表頭
                End If


                '列印細項內容


      '列印表尾

      '每頁的最後一筆之後,加印表尾
      If (startidx Mod linesPerPage = 0) Then

                      '這裡可以放表尾
                End If

                startidx += 1
                countt += 1

            End While

     

            '判斷換頁
            If endidx < tb.Rows.Count Then
                e.HasMorePages = True
            Else
                e.HasMorePages = False
            End If

     

            '若最後一頁不滿10筆則結束索引為最後一筆資料的索引
            If currentpage < totalPages Then
                startidx = currentpage * linesPerPage + 1
                If (currentpage + 1) * linesPerPage >= tb.Rows.Count Then
                    endidx = tb.Rows.Count
                Else
                    endidx = (currentpage + 1) * linesPerPage 
                End If

            End If

        End Sub

    2008年9月25日 上午 03:28
  • 移文到 VB 版

    2008年9月29日 上午 03:53
    版主