VB报告错误System.InvalidCastException:未为类型“Double”定义运算符“+”并键入“DBNull”

时间:2017-10-27 08:29:41

标签: vb.net sharepoint report

错误:错误行369

Line 367:        For intTeller = 0 To tblData.Rows.Count - 1
Line 368:            With tblData.Rows(intTeller)
Line 369:                .Item("Projected") = .Item("Sales") + .Item("ShippedNotInvoiced") + .Item("OpenOrdersCurrentPeriod")
Line 370:            End With
Line 371:        Next

代码

Imports System.Data.SqlClient
    Partial Class Sales
        Inherits System.Web.UI.Page
    Dim tblData As New Data.DataTable
    Private Sub DataGridToExcel(ByRef grdExport As GridView, ByRef pResponse As Web.HttpResponse, ByVal pFileName As String)
    Try
        Dim intTeller As Integer = 0
        Dim strTemp As String

        pResponse.Clear()
        pResponse.AddHeader("content-disposition", "attachment;filename=" & pFileName)
        pResponse.Buffer = True
        pResponse.ContentType = "application/vnd.ms-excel"
        pResponse.Charset = ""

        Dim stringWrite As New System.IO.StringWriter
        Dim htmlWrite As New System.Web.UI.HtmlTextWriter(stringWrite)

        grdExport.RenderControl(htmlWrite)
        strTemp = stringWrite.ToString
        strTemp.Replace(",", "")
        strTemp.Replace(".", "")
        pResponse.Write(strTemp)

        pResponse.End()

    Catch ex As Exception
        'Me.lblError.Text = ex.Message
    End Try

End Sub
Public Overrides Sub VerifyRenderingInServerForm(ByVal control As Control)

End Sub


Private Sub sExportGrid()

    DataGridToExcel(Me.grdSalesLines, Response, "Sales " & Format(Now, "yyyyMM") & ".xls")

End Sub

Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    If Not Page.IsPostBack Then

        sCreateTable()
        sFillPeriods()
        sRefreshData(Format(Now, "yyyyMM"), Format(DateAdd(DateInterval.Year, -1, Now), "yyyyMM"))



    End If
End Sub

Private Sub sFillPeriods()

    Dim conMain As New SqlConnection(sGetConnectionString)
    Dim comMain As SqlCommand
    Dim drMain As SqlDataReader

    Dim strSQL As String = "SELECT DISTINCT Period FROM [SR_SalesOverviewCompany] Order by Period DESC"
    conMain.Open()
    comMain = New SqlCommand(strSQL, conMain)

    drMain = comMain.ExecuteReader

    Me.cmbPeriods.Items.Clear()

    Me.cmbPeriods.Items.Add("Current Period")
    Me.cmbPeriods.Items.Add("Year To Date")

    If drMain.HasRows Then
        While drMain.Read
            If Not IsDBNull(drMain.Item("Period")) Then
                Me.cmbPeriods.Items.Add(drMain.Item("Period"))
            End If
        End While
    End If


End Sub
Private Function sGetConnectionString() As String

    Dim conString = ConfigurationManager.ConnectionStrings("STOKVIS LIVEConnectionString")
    Dim strConnString As String = conString.ConnectionString

    Return strConnString

End Function

Protected Sub grdSalesLines_DataBound(sender As Object, e As System.EventArgs) Handles grdSalesLines.DataBound

    If Me.cmbPeriods.SelectedItem.Text <> "Current Period" Then

        grdSalesLines.Columns(3).Visible = False
        grdSalesLines.Columns(4).Visible = False
        grdSalesLines.Columns(5).Visible = False
        grdSalesLines.Columns(7).Visible = False

    Else

        grdSalesLines.Columns(3).Visible = True
        grdSalesLines.Columns(4).Visible = True
        grdSalesLines.Columns(5).Visible = True
        grdSalesLines.Columns(7).Visible = True
    End If

End Sub

Protected Sub grdSalesLines_RowCommand(sender As Object, e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles grdSalesLines.RowCommand

    Dim intRow As Integer = CInt(e.CommandArgument)

    Response.Redirect("SalesDetails.aspx?p=" & Me.cmbPeriods.SelectedItem.Text & "&s=" & grdSalesLines.Rows(intRow).Cells(1).Text)

End Sub


Protected Sub grdSalesLines_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles grdSalesLines.RowDataBound
    Dim intCounter As Integer

    If e.Row.Cells(1).Text = "Total" Then

        For intCounter = 0 To e.Row.Cells.Count - 1

            With e.Row.Cells(intCounter)
                .ForeColor = Drawing.Color.White
                .BackColor = Drawing.Color.DarkBlue
                .Font.Bold = True
            End With

        Next

    End If
End Sub

Private Sub sCreateTable()

    tblData.Columns.Clear()

    tblData.Columns.Add(New Data.DataColumn("Code", System.Type.GetType("System.String")))
    tblData.Columns.Add(New Data.DataColumn("Salesperson", System.Type.GetType("System.String")))
    tblData.Columns.Add(New Data.DataColumn("OpenOrders", System.Type.GetType("System.Double")))
    tblData.Columns.Add(New Data.DataColumn("OpenOrdersCurrentPeriod", System.Type.GetType("System.Double")))
    tblData.Columns.Add(New Data.DataColumn("ShippedNotInvoiced", System.Type.GetType("System.Double")))
    tblData.Columns.Add(New Data.DataColumn("Sales", System.Type.GetType("System.Double")))
    tblData.Columns.Add(New Data.DataColumn("Projected", System.Type.GetType("System.Double")))
    tblData.Columns.Add(New Data.DataColumn("Budget", System.Type.GetType("System.Double")))
    tblData.Columns.Add(New Data.DataColumn("PreviousYear", System.Type.GetType("System.Double")))


End Sub




Protected Sub btnRefresh_Click(sender As Object, e As System.EventArgs) Handles btnRefresh.Click

    If Me.cmbPeriods.SelectedItem.Text = "Current Period" Then
        sRefreshData(Format(Now, "yyyyMM"), Format(DateAdd(DateInterval.Year, -1, Now), "yyyyMM"))
    Else
        sRefreshData(Me.cmbPeriods.SelectedItem.Text, "")
    End If

End Sub

Protected Sub btnExcel_Click(sender As Object, e As System.EventArgs) Handles btnExport.Click
    sExportGrid()
End Sub

Protected Sub cmbPeriods_SelectedIndexChanged(sender As Object, e As System.EventArgs) Handles cmbPeriods.SelectedIndexChanged
    sCreateTable()
    If Me.cmbPeriods.SelectedItem.Text = "Current Period" Then
        sRefreshData(Format(Now, "yyyyMM"), Format(DateAdd(DateInterval.Year, -1, Now), "yyyyMM"))
    Else
        sRefreshData(Me.cmbPeriods.SelectedItem.Text, "")
    End If

End Sub

Private Sub sRefreshData(pPeriod As String, pPreviousYearPeriod As String)
    Dim conMain As New SqlConnection(sGetConnectionString)
    Dim comMain As SqlCommand
    Dim drMain As SqlDataReader
    Dim dtRow As Data.DataRow
    Dim strSQL As String
    Dim intTeller As Integer
    Dim blnYearToDate As Boolean = False

    sCreateTable()
    If pPeriod = "Year To Date" Then
        pPeriod = ""
        blnYearToDate = True
    End If


    strSQL = "SELECT code, Name from SR_SalesPerson"

    conMain.Open()
    comMain = New SqlCommand(strSQL, conMain)

    drMain = comMain.ExecuteReader

    If drMain.HasRows Then
        While drMain.Read

            dtRow = tblData.NewRow()

            dtRow.Item("Code") = drMain.Item("Code")
            dtRow.Item("SalesPerson") = drMain.Item("Name")
            dtRow.Item("OpenOrders") = 0
            dtRow.Item("OpenOrdersCurrentPeriod") = 0
            dtRow.Item("ShippedNotInvoiced") = 0
            dtRow.Item("Sales") = 0
            dtRow.Item("Projected") = 0
            dtRow.Item("Budget") = 0
            dtRow.Item("PreviousYear") = 0

            tblData.Rows.Add(dtRow)
        End While
        dtRow = tblData.NewRow()

        dtRow.Item("Code") = "Total"
        dtRow.Item("SalesPerson") = ""
        dtRow.Item("OpenOrders") = 0
        dtRow.Item("OpenOrdersCurrentPeriod") = 0
        dtRow.Item("ShippedNotInvoiced") = 0
        dtRow.Item("Sales") = 0
        dtRow.Item("Projected") = 0
        dtRow.Item("Budget") = 0
        dtRow.Item("PreviousYear") = 0

        tblData.Rows.Add(dtRow)
    End If

    drMain.Close()
    comMain.Dispose()

    strSQL = "SELECT * FROM SR_SalesOpenOrdersShippedNotInvoiced"

    comMain = New SqlCommand(strSQL, conMain)

    drMain = comMain.ExecuteReader

    If drMain.HasRows Then
        While drMain.Read
            For intTeller = 0 To tblData.Rows.Count - 1
                If tblData.Rows(intTeller).Item("Code") = drMain.Item("Code") Then
                    tblData.Rows(intTeller).Item("ShippedNotInvoiced") = drMain.Item("AmountRest")
                End If
            Next
        End While
    End If

    drMain.Close()
    comMain.Dispose()

    strSQL = "SELECT * FROM SR_SalesOpenOrdersPerSalesperson"

    comMain = New SqlCommand(strSQL, conMain)

    drMain = comMain.ExecuteReader

    If drMain.HasRows Then
        While drMain.Read
            For intTeller = 0 To tblData.Rows.Count - 1
                If tblData.Rows(intTeller).Item("Code") = drMain.Item("Code") Then
                    tblData.Rows(intTeller).Item("OpenOrders") = drMain.Item("OpenOrders")
                End If
            Next
        End While
    End If

    drMain.Close()
    comMain.Dispose()

    strSQL = "SELECT * FROM SR_SalesOpenOrdersPerSalesPersonPerPeriod WHERE Period='" & pPeriod & "'"

    comMain = New SqlCommand(strSQL, conMain)

    drMain = comMain.ExecuteReader

    If drMain.HasRows Then
        While drMain.Read
            For intTeller = 0 To tblData.Rows.Count - 1
                If tblData.Rows(intTeller).Item("Code") = drMain.Item("SalesPerson Code") Then
                    tblData.Rows(intTeller).Item("OpenOrdersCurrentPeriod") = drMain.Item("AmountRest")
                End If
            Next
        End While
    End If


    drMain.Close()
    comMain.Dispose()

    strSQL = "SELECT * FROM SR_BudgetPerSalesPersonPerPeriod WHERE strPeriod='" & pPeriod & "'"

    comMain = New SqlCommand(strSQL, conMain)

    drMain = comMain.ExecuteReader

    If drMain.HasRows Then
        While drMain.Read
            For intTeller = 0 To tblData.Rows.Count - 1
                If tblData.Rows(intTeller).Item("Code") = drMain.Item("strCode") Then
                    tblData.Rows(intTeller).Item("Budget") = drMain.Item("dblSales")
                End If
            Next
        End While
    End If

    drMain.Close()
    comMain.Dispose()


    strSQL = "SELECT * FROM SR_HistSalesPerSalesPersonPerPeriod WHERE strPeriod='" & pPreviousYearPeriod & "'"

    comMain = New SqlCommand(strSQL, conMain)

    drMain = comMain.ExecuteReader

    If drMain.HasRows Then
        While drMain.Read
            For intTeller = 0 To tblData.Rows.Count - 1
                If tblData.Rows(intTeller).Item("Code") = drMain.Item("strCode") Then
                    tblData.Rows(intTeller).Item("PreviousYear") = drMain.Item("dblSales")
                End If
            Next
        End While
    End If

    drMain.Close()
    comMain.Dispose()
    If blnYearToDate Then
        strSQL = "SELECT Salesperson, SUM(Sales) AS Sales, SUM([Cost of Sales]) AS [Cost of Sales], SUM(Margin) AS Margin, SUM(Margin) / SUM(Sales) AS SalesPercent, Code " & _
                        "FROM dbo.SR_SalesPerSalesperson " & _
                        "WHERE (Period LIKE '" & Now.Year & "%') " & _
                        "GROUP BY Salesperson, Code"
    Else
        strSQL = "SELECT * FROM SR_SalesPerSalesperson WHERE Period='" & pPeriod & "'"
    End If

    comMain = New SqlCommand(strSQL, conMain)

    drMain = comMain.ExecuteReader

    If drMain.HasRows Then
        While drMain.Read
            For intTeller = 0 To tblData.Rows.Count - 1
                If tblData.Rows(intTeller).Item("Code") = drMain.Item("Code") Then
                    tblData.Rows(intTeller).Item("Sales") = drMain.Item("Sales")
                End If
            Next
        End While
    End If

    For intTeller = 0 To tblData.Rows.Count - 1
        With tblData.Rows(intTeller)
            .Item("Projected") = .Item("Sales") + .Item("ShippedNotInvoiced") + .Item("OpenOrdersCurrentPeriod")
        End With
    Next


    Dim intLastRow As Integer = tblData.Rows.Count - 1

    For intTeller = 0 To tblData.Rows.Count - 2
        With tblData.Rows(intTeller)
            tblData.Rows(intLastRow).Item("Sales") += fCheckValue(.Item("Sales"))
            tblData.Rows(intLastRow).Item("OpenOrders") += fCheckValue(.Item("OpenOrders"))
            tblData.Rows(intLastRow).Item("OpenOrdersCurrentPeriod") += fCheckValue(.Item("OpenOrdersCurrentPeriod"))
            tblData.Rows(intLastRow).Item("ShippedNotInvoiced") += fCheckValue(.Item("ShippedNotInvoiced"))
            tblData.Rows(intLastRow).Item("Projected") += fCheckValue(.Item("Projected"))
            tblData.Rows(intLastRow).Item("Budget") += fCheckValue(.Item("Budget"))
            tblData.Rows(intLastRow).Item("PreviousYear") += fCheckValue(.Item("PreviousYear"))
        End With

    Next

    Me.grdSalesLines.DataSource = tblData
    Me.grdSalesLines.DataBind()


    Try
        drMain.Close()
        comMain.Dispose()
        conMain.Close()
    Catch ex As Exception

    End Try

End Sub

Private Function fCheckValue(pField As Object) As Double

    Dim dblValue As Double = 0

    If IsDBNull(pField) Then
        dblValue = 0
    Else
        dblValue = CDbl(pField)
    End If


    Return dblValue
End Function

End Class

1 个答案:

答案 0 :(得分:1)

首先,拥有一个辅助函数可能很有用,如下所示:

Private Function GetNullableValue(Of T)(ByVal dataRow As DataRow, ByVal columnName As String, ByVal defaultIfNull As T) As T

    If Not IsDBNull(dataRow.Item(columnName)) Then
        Return CType(dataRow.Item(columnName), T)
    End If

    Return CType(defaultIfNull, T)

End Function

要检查DBNull,您可以按如下方式修改代码:

For intTeller = 0 To tblData.Rows.Count - 1
    Dim row As DataRow = tblData.Rows(intTeller)
    With row
        .Item("Projected") = GetNullableValue(row, "Sales", 0) + GetNullableValue(row, "ShippedNotInvoiced", 0) + GetNullableValue(row, "OpenOrdersCurrentPeriod", 0)
    End With
Next

注意:以上内容应该是例外的一步。然而,这些列中的一列为空的事实可能表示另一个问题 - 例如也许查询或数据存在问题