我正在try 在VB.NET中以打印预览和直接打印的方式以HTML格式打印DataTable的内容,包括页眉/设置纸张/方向/适合页面.

也许在rdlc报告中很容易做到这一点,但我不能使用它,因为字符名称属性问题不允许这样做.

所以我采取了这个解决方案,将其转换为html,或者还有其他解决方案,请给我建议

我有下面的代码,但这仍然是错误的.

还有没有别的办法,请给我带路

谢谢

Private dt As New DataTable
    Private Function CreateConnection() As OleDbConnection
        Return New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\transposerowtocolumnsqlmsaccessvbnet.accdb;Persist Security Info=False;")
    End Function
    Private Function LoadData() As DataTable
        Dim dt As New DataTable()

        Using con = CreateConnection(), cmd = con.CreateCommand(),
        ta = New OleDbDataAdapter(cmd)
            Dim sql = <sql>
                          TRANSFORM Sum(Tableproduct.Qty) AS SumOfQty
SELECT Tableproduct.Codeproduct AS CodeProduct, Tableproduct.Colour AS Colour, Sum(Tableproduct.Qty) AS Total
FROM Tableproduct INNER JOIN SizeProduct ON Tableproduct.Size = SizeProduct.Size
WHERE (((Tableproduct.Codeproduct)='B'))
GROUP BY Tableproduct.Codeproduct, Tableproduct.Colour
PIVOT SizeProduct.Size;
                      </sql>.Value
            cmd.CommandText = sql
            ta.Fill(dt)
        End Using
        Return dt
    End Function
 Private Function ExportDatatableToHtml(ByVal dt As DataTable) As String
        Dim stringBuilder As New StringBuilder()
        stringBuilder.Append("<html >")
        stringBuilder.Append("<head>")
        stringBuilder.Append("<meta charset='utf-8'>")
        stringBuilder.Append("</head>")
        stringBuilder.Append("<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css' integrity='sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk' crossorigin='anonymous'>")
        stringBuilder.Append("<script src='https://code.jquery.com/jquery-3.3.1.slim.min.js' integrity='sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo' crossorigin='anonymous'></script>")
        stringBuilder.Append("<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js' integrity='sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy' crossorigin='anonymous'></script>")
        stringBuilder.Append("<body>")
        stringBuilder.Append("<table class='table table-sm table-hover' style='margin: 20px;'>")
        stringBuilder.Append("<thead>")
        stringBuilder.Append("<tr class='bg-primary' style='color: white; text-align: left;'>")
        For Each column As DataColumn In dt.Columns
            stringBuilder.Append("<th class='border border-secondary'>")
            stringBuilder.Append(column.ColumnName)
            stringBuilder.Append("</th>")
        Next column
        stringBuilder.Append("</tr>")
        stringBuilder.Append("</thead>")
        For Each row As DataRow In dt.Rows
            stringBuilder.Append("<tr>")
            For Each column As DataColumn In dt.Columns
                stringBuilder.Append("<td class='border border-secondary'>")
                stringBuilder.Append(row(column.ColumnName).ToString())
                stringBuilder.Append("</td>")
            Next column
            stringBuilder.Append("</tr>")
        Next row
        stringBuilder.Append("</table>")
        stringBuilder.Append("</body>")
        stringBuilder.Append("</html>")
        Dim html = stringBuilder.ToString()
        Return html
    End Function

    Private Sub BRNCONVERT_Click(sender As Object, e As EventArgs) Handles BRNCONVERT.Click
        Using saveFileDialog As New SaveFileDialog() With {.Filter = "Html files|*.html"}
            If saveFileDialog.ShowDialog() = DialogResult.OK Then
                Dim html As String = ExportDatatableToHtml(LoadData())
                System.IO.File.WriteAllText(saveFileDialog.FileName, html)
            End If
        End Using

    End Sub

上述代码的结果:

Result in html for codeproductA

Result in html for codeproductB

下面包括我要设置的内容:

  • 文档大小:A5
  • 缩小/放大文档:适合页面大小
  • 朝向:风景
  • 总和
  • 标题标题
  • Invono页眉

样本数据:

表格表产品

CodeProduct Colour Size Qty
A White S 15
A Black M 20
A White L 10
A - 20
A XXL/2L 15
B Blue S 20
B White XL 15

桌子大小产品

Sizeproduct Sequence
- 1
S 2
M 3
L 4
XL 5
XXL/2L 6

期望的结果

对于代码产品=A

            SAMPLE

调用:1000

CodeProduct Colour - S M L XL TOTAL
A 20 10 35
A Black 20 20
A White 15 10 25
                       总和 : 80

对于代码产品=B

            SAMPLE

调用:1000

CodeProduct Colour S XL TOTAL
B Blue 20 20
B White 15 10
               总和 : 30

打印码

Private stringtoPrint as string
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim htmlFile = "test.html"

        Using dt = LoadData("A")
            File.WriteAllText(htmlFile, DataTableToHtml(dt))
        End Using
End Sub
Private Sub ReadFile()
        Dim docName As String = "test.html"
        Dim docPath As String = CType(AppDomain.CurrentDomain.GetData("DataDirectory"), String)
        pd.DocumentName = docName
        Dim stream As New FileStream(docPath + docName, FileMode.Open)
        Try
            Dim reader As New StreamReader(stream)
            Try
                stringToPrint = reader.ReadToEnd()
            Finally
                reader.Dispose()
            End Try
        Finally
            stream.Dispose()
        End Try
    End Sub

 Private Sub Btnprint_Click(sender As Object, e As EventArgs) Handles Btnprint.Click
 Try
            ReadFile()
            Dim ps As New PrinterSettings()
            Dim paperSizes As IEnumerable(Of PaperSize) = ps.PaperSizes.Cast(Of PaperSize)()
            Dim sizeA5 As PaperSize = paperSizes.First(Function(size) size.Kind = PaperKind.A5) ' setting paper size to A4 size
            pd.DefaultPageSettings.PaperSize = sizeA5
            pd.DefaultPageSettings.Landscape = True
            Dim preview As New PrintPreviewDialog()
            preview.Document = pd
            preview.Show()
            'pd.Print()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

  Private Sub pd_PrintPage(ByVal sender As Object, ByVal e As PrintPageEventArgs) Handles pd.PrintPage
        Dim charactersOnPage As Integer = 0
        Dim linesPerPage As Integer = 0

        ' Sets the value of charactersOnPage to the number of characters 
        ' of stringToPrint that will fit within the bounds of the page.
        e.Graphics.MeasureString(stringToPrint, Me.Font, e.MarginBounds.Size,
            StringFormat.GenericTypographic, charactersOnPage, linesPerPage)

        ' Draws the string within the bounds of the page
        e.Graphics.DrawString(stringToPrint, Me.Font, Brushes.Black,
            e.MarginBounds, StringFormat.GenericTypographic)

        ' Remove the portion of the string that has been printed.
        stringToPrint = stringToPrint.Substring(charactersOnPage)

        ' Check to see if more pages are to be printed.
        e.HasMorePages = stringToPrint.Length > 0


    End Sub

推荐答案

The Crosstab Query

考虑问题中表格的设计.TableProductSizeProduct表之间没有数据库关系.它们有一个重复的字段,只有这个字段并不意味着这两个表是相关的.这意味着,查询中的JOIN部分根本没有意义.你不需要连接表中的任何东西,因为你已经在TableProduct中有了pivot field.因此,查询应该是这样的:

TRANSFORM Sum(Tableproduct.Qty) AS SumOfQty
SELECT Tableproduct.Codeproduct AS CodeProduct, 
       Tableproduct.Color AS Color, 
       Sum(Tableproduct.Qty) AS Total
FROM Tableproduct
WHERE Tableproduct.Codeproduct = 'A'
GROUP BY Tableproduct.Codeproduct, Tableproduct.Color
PIVOT Tableproduct.Size;

要按大小的升序 Select pivot field,请执行以下操作:

PIVOT Tableproduct.Size IN ('-', 'S', 'M', 'L', 'XL', 'XXL/2L');

如果TableProduct包含foreign key字段,并保留SizeProduct表中相关的唯一primary key个值,那么您的查询就有意义了.然后我们可以说这两个表之间存在关系,JOIN是从ProductSize表中获得pivot field所必需的.

TRANSFORM Sum(Tableproduct.Qty) AS SumOfQty
SELECT Tableproduct.Codeproduct AS CodeProduct,
       Tableproduct.Color AS Color,
       Sum(Tableproduct.Qty) AS Total
FROM Tableproduct 
INNER JOIN SizeProduct ON Tableproduct.SizeId = SizeProduct.Id
WHERE Tableproduct.Codeproduct = 'A'
GROUP BY Tableproduct.Codeproduct, Tableproduct.Color
PIVOT SizeProduct.Size;

For more, please read:
How to define relationships between tables in an Access database.


DataTable to HTML Table

现在,我们应该有一个运行交叉表查询的方法,填充并返回DataTable,如下所示:

Private Function LoadData(code As String) As DataTable
    Dim dt As New DataTable()
    Dim sql = <sql>
    TRANSFORM Sum(Tableproduct.Qty) AS SumOfQty
    SELECT Tableproduct.Codeproduct AS CodeProduct,
           Tableproduct.Color AS Color,
           Sum(Tableproduct.Qty) AS Total
    FROM Tableproduct 
    WHERE Tableproduct.Codeproduct = '<%= code %>'
    GROUP BY Tableproduct.Codeproduct, Tableproduct.Color
    PIVOT Tableproduct.Size IN ('-', 'S', 'M', 'L', 'XL', 'XXL/2L');
    </sql>.Value

    Using con = CreateConnection(),
          cmd = New OleDbCommand(sql, con),
          ta = New OleDbDataAdapter(cmd)
        ta.Fill(dt)
    End Using

    ' Make it the last column.
    dt.Columns("Total").SetOrdinal(dt.Columns.Count - 1)
    Return dt
End Function

或此版本以排除空列:

Private Function LoadData(code As String) As DataTable
    Using dt As New DataTable()
        Dim sql = <sql>
        TRANSFORM Sum(Tableproduct.Qty) AS SumOfQty
        SELECT Tableproduct.Codeproduct AS CodeProduct,
               Tableproduct.Color AS Color,
               Sum(Tableproduct.Qty) AS Total
        FROM Tableproduct 
        WHERE Tableproduct.Codeproduct = '<%= code %>'
        GROUP BY Tableproduct.Codeproduct, Tableproduct.Color
        PIVOT Tableproduct.Size IN ('-', 'S', 'M', 'L', 'XL', 'XXL/2L');
        </sql>.Value

        Using con = CreateConnection(),
              cmd = New OleDbCommand(sql, con),
              ta = New OleDbDataAdapter(cmd)
            ta.Fill(dt)
        End Using

        dt.Columns("Total").SetOrdinal(dt.Columns.Count - 1)

        Dim cols = dt.Columns.Cast(Of DataColumn).
        Where(Function(col) CInt(dt.Compute($"COUNT(`{col.ColumnName}`)", $"`{col.ColumnName}` IS NOT NULL")) > 0).
        Select(Function(col) col.ColumnName).ToArray()

        Return dt.DefaultView.ToTable(False, cols)
    End Using
End Function

一种创建包含grand total值的HTML输出的方法.

Private Function DataTableToHtml(dt As DataTable) As String
    Dim Invono = "ABC123"
    Dim html =
        <html>
            <head>
                <meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
                <style>
                table.tb { border-collapse: collapse; width: 100%; }
                .tb th, .tb td { padding: 5px; border: solid 1px; text-align: center; }
                .tb th { background-color: lightblue;}</style>
            </head>
            <body>
                <h2 style="margin-bottom: 0.3em">Some Title</h2>
                <p>
                    <b>Invono: </b><%= Invono %><br/>
                    <b>More Info:</b> Whatever...
                </p>
                <table class="tb">
                    <thead>
                        <tr>
                            <%= dt.Columns.Cast(Of DataColumn).
                                    Select(Function(col) <th><%= col.ColumnName %></th>) %>
                        </tr>
                    </thead>
                    <tbody>
                        <%= dt.AsEnumerable().Select(
                            Function(row)
                                Return _
                                <tr>
                                    <%=
                                        row.ItemArray.OfType(Of Object).Select(
                                    Function(cell) <td><%= cell.ToString() %></td>)
                                    %>
                                </tr>
                            End Function) %>
                        <tr>
                            <td style="border: 0px; text-align: right;" colspan=<%= dt.Columns.Count - 1 %>><strong>Grand Total</strong></td>
                            <td><strong><%= dt.Compute("SUM(Total)", Nothing) %></strong></td>
                        </tr>
                    </tbody>
                </table>
            </body>
        </html>

    Return html.ToString()
End Function

实现如下所示:

Private Sub SomeButton_Click(sender As Object, e As EventArgs) Handles SomeButton.Click
    Dim htmlFile = "..."

    Using dt = LoadData("A")
        File.WriteAllText(htmlFile, DataTableToHtml(dt))
    End Using
End Sub

SO77371933A

SO77371933B

你没有展示印刷部分.但是,这里的html表将填充页面边界的宽度,而不管您在打印对话框中指定的页面大小、边距和方向如何.

Html相关问答推荐

CSS Flex行之间的空间很大

为什么在这种情况下是弹性基础:自动不解决内容的大小?

动态FormControl值在Angular 上绑定错误的问题

在Chrome中使用手写笔时,滚动条方向反转

仅向上扩展并以最大高度滚动的Div

如何使链接组件内的内容不重新路由Next.js13

如何在 Bootstrap 5 中将两个导航栏元素放在末尾?

如何在悬停时使用 CSS 更改许多同级元素

为 HTML5 文本字段设置最后六位正则表达式模式

如何使Bootstrap 5卡可点击

如何将内容放置在侧边栏旁边?

如何围绕中心zoom svg 并使父级达到其子级大小的 100%

在Angular中,类型"HTMLDivElement"不能分配给类型"Node"

如何使用CSS Select 同级元素的::before伪元素?

为什么每当我调整图片大小时它都会使我的其他元素移动

为什么 css position:fixed 不适用于对话框标签?

如何将某些 div 的高度限制为具有 display flex 行的同一父 div 中的其他 div?

不理解 CSS 中的 General sibling combinator (~)

在 EJS 中将元素放置在彼此下方的列中

是否可以在换行时向锚标记添加填充?