将过滤后的 Datagridview 导出为 excel 或 pdf (SQL Server)

Posted

技术标签:

【中文标题】将过滤后的 Datagridview 导出为 excel 或 pdf (SQL Server)【英文标题】:Exporting Filtered Datagridview to excel or pdf (SQL Server) 【发布时间】:2021-12-11 01:58:17 【问题描述】:

我希望我的应用程序导出 datagridview 上的任何内容,包括过滤器。这是我的应用程序的布局:

组合框包含所有列的名称。搜索栏搜索该列内的数据。代码是这样的:

Imports System.Data.SqlClient
Imports System.IO
Imports ClosedXML.Excel
Imports System.Data.DataSetExtensions.dll
Public Class export
Dim con As New SqlConnection("Data Source=ICECANDY;Initial Catalog=RestaurantDatabase;integrated security=true")

Sub DGVSETPROPERTY()
    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "TaskID"

    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "Name"

    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "TaskCategory"

    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "TaskAssigned"

    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "TimeIssued"

    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "TargetTime"

    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "StartTime"

    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "FinishTime"

    DataGridView1.Columns(0).Width = 40
    DataGridView1.Columns(0).HeaderText = "Status"
End Sub
Sub view()
    Try
        Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks]", con)
        Dim bumrah As New DataSet()
        singh.Fill(bumrah)
        DataGridView1.DataSource = bumrah.Tables(0)
        DGVSETPROPERTY()

    Catch ex As Exception
        MessageBox.Show(ex.ToString())
    End Try
End Sub
Private Sub export_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    view()
End Sub

Private Sub export_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    Panel1.Left = (Me.Width - Panel1.Width) / 2
End Sub

Private Sub txtsearch_TextChanged(sender As Object, e As EventArgs) Handles txtsearch.TextChanged
    Try
        If ComboBox.Text = "TaskID" Then
            Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory]
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks] where TaskID Like '" + txtsearch.Text + "%'", con)
            Dim bumrah As New DataSet()
            singh.Fill(bumrah)
            DataGridView1.DataSource = bumrah.Tables(0)

        ElseIf ComboBox.Text = "Name" Then
            Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks] where Name Like '" + txtsearch.Text + "%'", con)
            Dim bumrah As New DataSet()
            singh.Fill(bumrah)
            DataGridView1.DataSource = bumrah.Tables(0)

        ElseIf ComboBox.Text = "TaskCategory" Then
            Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks] where TaskCategory Like '" + txtsearch.Text + "%'", con)
            Dim bumrah As New DataSet()
            singh.Fill(bumrah)
            DataGridView1.DataSource = bumrah.Tables(0)

        ElseIf ComboBox.Text = "TimeIssued" Then
            Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks] where TimeIssued Like '" + txtsearch.Text + "%'", con)
            Dim bumrah As New DataSet()
            singh.Fill(bumrah)
            DataGridView1.DataSource = bumrah.Tables(0)

        ElseIf ComboBox.Text = "TargetTime" Then
            Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks] where TargetTime Like '" + txtsearch.Text + "%'", con)
            Dim bumrah As New DataSet()
            singh.Fill(bumrah)
            DataGridView1.DataSource = bumrah.Tables(0)

        ElseIf ComboBox.Text = "StartTime" Then
            Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks] where StartTime Like '" + txtsearch.Text + "%'", con)
            Dim bumrah As New DataSet()
            singh.Fill(bumrah)
            DataGridView1.DataSource = bumrah.Tables(0)

        ElseIf ComboBox.Text = "FinishTime" Then
            Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks] where FinishTime Like '" + txtsearch.Text + "%'", con)
            Dim bumrah As New DataSet()
            singh.Fill(bumrah)
            DataGridView1.DataSource = bumrah.Tables(0)

        ElseIf ComboBox.Text = "Status" Then
            Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks] where Status Like '" + txtsearch.Text + "%'", con)
            Dim bumrah As New DataSet()
            singh.Fill(bumrah)
            DataGridView1.DataSource = bumrah.Tables(0)

        End If

    Catch ex As Exception
        MessageBox.Show(ex.ToString())
    End Try
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Try
        Dim singh As New SqlDataAdapter("SELECT TOP (1000) [TaskID]
  ,[Name]
  ,[TaskCategory] 
  ,[TaskAssigned]
  ,[TimeIssued]
  ,[TargetTime]
  ,[StartTime]
  ,[FinishTime]
  ,[Status]
FROM [RestaurantDatabase].[dbo].[Tasks]", con)
        Dim bumrah As New DataSet()
        singh.Fill(bumrah)
        DataGridView1.DataSource = bumrah.Tables(0)
        DGVSETPROPERTY()
    Catch ex As Exception
        MessageBox.Show(ex.ToString())
    End Try
End Sub

End Class

我想导出过滤后的数据。 pdf或excel都可以。

【问题讨论】:

连接应该在使用它们的方法中的使用块中声明。他们必须调用 Dispose 方法,然后 End Using 执行此操作并关闭连接。 不要连接 SQL 字符串。使用参数。 如果您只使用DataAdapter 中的单个表,请不要使用DataSet,使用DataTable 为了弄清楚这一点,您已经成功地从数据库中提取了您想要的数据(甚至在玛丽提出非常有效的建议之前)?现在您希望将其导出?如果是这样的话,这一切都很好,很好地向我们展示了有效的代码,但是尝试导出无效的代码呢?已经有大量示例和现有工具可以做到这一点 【参考方案1】:

编程中有一个原则叫做 DRY。它代表不要重复自己。我想你可以看到你违反了这个原则。当你构建 Sql 字符串时,就像我在这里所做的那样,小心空格。你需要在单词之间留一个空格。我试图把它放在字符串的末尾。 Debug.Print 将显示字符串是否正确输出。

当您有一系列针对相同值的 If 语句时,Select Case 更易于阅读和编写。

不必将列标题添加到 DataGridView。 DataTable 到网格的绑定将处理这个问题。我相信这些列会自动调整大小以适应数据。

ADO.net 中的几个数据库对象提供了一个 Dispose 方法,用于释放非托管资源。如果有一个 Dispose 方法,它应该被调用。 Using...End Using 块即使出现错误也会为我们执行此操作(它也会关闭连接)。这些对象需要在 Using 块中使用它们的方法中声明。

不要乱用 DataGridView。您只需要 DataTable 即可与 Excel 进行交互。

关闭 Excel 的 Wrapper 可能看起来很奇怪,但 Excel 在 b_tch 中可以摆脱。我相信这里的安排是可行的。

Private Sub txtsearch_TextChanged(sender As Object, e As EventArgs) Handles txtsearch.TextChanged
    Dim Field = ComboBox1.Text
    Dim strSQL = "SELECT TOP (1000) 
                [TaskID],
                [Name],
                [TaskCategory],
                [TaskAssigned],
                [TimeIssued],
                [TargetTime],
                [StartTime],
                [FinishTime],
                [Status]
                FROM [RestaurantDatabase].[dbo].[Tasks] 
                WHERE "

    Select Case Field
            Case "TaskID"
                strSQL &= "TaskID "
            Case "Name"
                strSQL &= "Name "
            Case "TaskCategory"
                strSQL &= "TaskCategory "
            Case "TimeIssued"
                strSQL &= "TimeIssued "
            Case "TargetTime"
                strSQL &= "TargetTime "
            Case "StartTime"
                strSQL = "StartTime "
            Case "FinishTime"
                strSQL &= "FinishTime "
            Case "Status"
                strSQL &= "Status "
        End Select
    strSQL &= "Like @Search;"
    Debug.Print(strSQL)
    Dim dt As New DataTable
    Try
        Using cn As New SqlConnection(OPConStr),
                        cmd As New SqlCommand(strSQL, cn)
            cmd.Parameters.Add("@Search", SqlDbType.VarChar).Value = txtsearch.Text & "%"
            cn.Open()
            Using reader = cmd.ExecuteReader
                dt.Load(reader)
            End Using
        End Using
    Catch ex As Exception
        MessageBox.Show(ex.ToString())
    End Try
    DataGridView1.DataSource = dt
    WrapperToGetRidOfExcel(dt)
End Sub

Private Sub WrapperToGetRidOfExcel(dt As DataTable)
    FillExcelFromDataTable(dt)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

Private Sub FillExcelFromDataTable(dt As DataTable)
    Dim oExcel As New Excel.Application
    Dim oBook = oExcel.Workbooks.Add
    Dim oSheet = DirectCast(oBook.Worksheets.Add, Excel.Worksheet)
    Dim ColumnIndex = 1 'in the Excel worksheet
    For Each col As DataColumn In dt.Columns 'This loop adds the header row
        oSheet.Cells(1, ColumnIndex) = col.ColumnName
        ColumnIndex += 1
    Next
    ColumnIndex = 1 'The columns and rows in the spreadsheet
    Dim RowIndex = 2 'The columns and rows in the spreadsheet
    For rowI = 0 To dt.Rows.Count - 1
        For Each col As DataColumn In dt.Columns
            oSheet.Cells(RowIndex, ColumnIndex) = dt(rowI)(col)
            ColumnIndex += 1
        Next
        ColumnIndex = 1 'Reset back to the first column
        RowIndex += 1
    Next
    oBook.Save()
    oBook.SaveAs(Filename:="ExcelDat.xlsx") 
    oBook.Close()
    oExcel.Quit()
End Sub

【讨论】:

感谢您的回答。我回家后会试试这个。很抱歉在编程方面缺乏能力。我只是在youtube上观看了视频以进行测试。我真的很感激帮助!我希望你有一个美好的一天。 另外一个问题,如何在您的代码中启动导出到 excel 功能?我没有看到激活它的按钮或其他东西。 txtsearch_TextChanged 的​​最后一行调用了包装器。包装器调用 Excel 的东西。 如何才能使导出仅在我按下按钮时才有效?我只是将包装器移到按钮上吗?我尝试了代码,但每次我在 txtsearch 文本框中输入内容时它都会导出。 @Andre'Bella 那是因为它开始于一个 TextChanged 事件,该事件在您每次键入字符时触发。使用按钮的好主意。将 TextChanged 中的所有代码移出到 button.Click.

以上是关于将过滤后的 Datagridview 导出为 excel 或 pdf (SQL Server)的主要内容,如果未能解决你的问题,请参考以下文章

在 vb net 中显示从 1 个平板电脑到 2 个过滤后的 datagridview 的数据

从管理产品网格将产品导出到 csv

将 DataGridView 导出到文本文件,保持列对齐

如何在 VB.NET 中将 DataGridView 导出为 Excel 格式

text 将数据导出为ex​​cel

text 将数组导出为ex​​cel