Home > Software engineering >  Datatable with column expression
Datatable with column expression

Time:07-27

I'm trying to use datatable columns with expression but when a load data, some columns works and other shows "Cannot perform '*' operation on System.Double and System.String"

I use this procedure in vb.net

  1. Load datatable from datareader
  2. Assign previous load expressions to defined columns
  3. List items in html table

I’m using this dataset with data between of columns with Expression.

enter image description here

Can you help me?

UPDATE:

typo: instead of IVA in the first appearance I mean IVAP, the next column name IVA is correct

the image is data copied from SQL management studio over excel with explains about the situation

this is my code

            Dim dtFinalData As New DataTable("DataProcessed")

            For i As Integer = 1 To objReader.FieldCount - 1

                    Dim cColumName As DataColumn = New DataColumn
                    With cDiff
                        .DataType = System.Type.GetType("System.Double")
                        .ColumnName = objReader.GetName(i).ToString()
                    End With
                    dtFinalData.Columns.Add(cColumName)

            Next

            Dim cColWithExpression1 As DataColumn = New DataColumn
            With cColWithExpression1
                .DataType = System.Type.GetType("System.Double")
                .ColumnName = "PCONDT"
                .Expression = "PSINIVA - (PSINIVA * (Discount/100))"
            End With
            dtFinalData.Columns.Add(cColWithExpression1)

            Dim cColWithExpression2 As DataColumn = New DataColumn
            With cColWithExpression2
                .DataType = System.Type.GetType("System.Double")
                .ColumnName = "Ivap"
                .Expression = "(PCONIVA-PCONDT)*Units"
            End With
            dtFinalData.Columns.Add(cColWithExpression2)

            Dim cCol As DataColumn = New DataColumn
            With cCol
                .DataType = System.Type.GetType("System.Double")
                .ColumnName = "IVA"
                .DefaultValue = 21
            End With
            dtFinalData.Columns.Add(cCol)                   

            Dim cColWithExpression3 As DataColumn = New DataColumn
            With cColWithExpression3
                .DataType = System.Type.GetType("System.Double")
                .ColumnName = "PCONIVA"
                .Expression = "(PCONDT*(1 (IVA/100)))"
            End With
            dtFinalData.Columns.Add(cColWithExpression3)    

            If objReader.HasRows Then
                While objReader.Read()
                        Dim RecordRow As DataRow = dtFinalData.NewRow
                        
                        RecordRow("Units") = objReader.Item("Units")
                        RecordRow("PSINIVA") = objReader.Item("PSINIVA")
                        RecordRow("PU") = objReader.Item("PU")
                        RecordRow("IVA") = objReader.Item("IVA")
                        dtFinalData.Rows.Add(RecordRow)
                End While
            End If      

UPDATE 2 - SOLVED (I think)

Thanks everyone for the answers, I found the procedure to work with the cascade of column expression, in datatable

  1. Create datatable with column names and numeric data type . In my case UNITS, PSINIVA, PU, DISCOUNT, IVA (I adjust my data source which is in a SQLDatareader to add IVA data column from database)

  2. Add values from data source

  3. Add columns definition with name, data type and the specific formula (Expression) but in sequence, where the previously column complete their data before the next formula. In my case first expression column must be PCONDT, next EXENT, next PCONIVA, and final IVAP

Using parts of the original code (perhaps not so performant), this is the final code

        Dim dtFinalData As New DataTable("DataProcessed")

        For i As Integer = 1 To objReader.FieldCount - 1

                Dim cColumName As DataColumn = New DataColumn
                With cDiff
                    .DataType = System.Type.GetType("System.Double")
                    .ColumnName = objReader.GetName(i).ToString()
                End With
                dtFinalData.Columns.Add(cColumName)

        Next
        
        If objReader.HasRows Then
            While objReader.Read()
                    Dim RecordRow As DataRow = dtFinalData.NewRow
                    RecordRow("Units") = objReader.Item("Units")
                    RecordRow("PSINIVA") = objReader.Item("PSINIVA")
                    RecordRow("PU") = objReader.Item("PU")
                    RecordRow("Discount") = objReader.Item("Discount")
                    RecordRow("IVA") = objReader.Item("IVA")
                    dtFinalData.Rows.Add(RecordRow)
            End While
        End If      
           
        Dim cColWithExpression1 As DataColumn = New DataColumn
        With cColWithExpression1
            .DataType = System.Type.GetType("System.Double")
            .ColumnName = "PCONDT"
            .Expression = "PSINIVA - (PSINIVA * (Discount/100))"
        End With
        dtFinalData.Columns.Add(cColWithExpression1)

        Dim cColWithExpression2 As DataColumn = New DataColumn
        With cColWithExpression2
            .DataType = System.Type.GetType("System.Double")
            .ColumnName = "EXENT"
            .Expression = "IIF(IVA=0,PCONDT*Units,0) "
        End With
        dtFinalData.Columns.Add(cColWithExpression2)

        Dim cColWithExpression3 As DataColumn = New DataColumn
        With cColWithExpression3
            .DataType = System.Type.GetType("System.Double")
            .ColumnName = "PCONIVA"
            .Expression = "(PCONDT*(1 (IVA/100)))"
        End With
        dtFinalData.Columns.Add(cColWithExpression3)    


        Dim cColWithExpression4 As DataColumn = New DataColumn
        With cColWithExpression4
            .DataType = System.Type.GetType("System.Double")
            .ColumnName = "Ivap"
            .Expression = "(PCONIVA-PCONDT)*Units"
        End With
        dtFinalData.Columns.Add(cColWithExpression4)

This is how data appears, after this code enter image description here

CodePudding user response:

It appears your PCONDT and PCONIVA columns are of type String. Change them to a numeric type and your formulas should work.

CodePudding user response:

Consider using Visual Studio's in-built DataSet tool instead. With it you can easily accomplish all that you've described, with much less effort.

enter image description here

For example, here's the definition for the PCONDT column:

enter image description here

This code:

Private Sub TestDataSet()
  Dim oTable As Test.Db.DataProcessedDataTable
  Dim oRow1 As Test.Db.DataProcessedRow
  Dim oRow2 As Test.Db.DataProcessedRow
  Dim oDb As Test.Db

  oDb = New Test.Db
  oTable = oDb.DataProcessed
  oRow1 = oTable.NewDataProcessedRow
  oRow2 = oTable.NewDataProcessedRow

  oRow1.Units = 2
  oRow1.PSINIVA = 20
  oRow1.PU = 20
  oRow1.Discount = 10
  oRow1.IVA = 21

  oRow2.Units = 1
  oRow2.PSINIVA = 100
  oRow2.PU = 100
  oRow2.Discount = 0
  oRow2.IVA = 21

  oTable.AddDataProcessedRow(oRow1)
  oTable.AddDataProcessedRow(oRow2)

  oDb.WriteXml("Db.xml")
End Sub

...produces this XML:

<?xml version="1.0" standalone="yes"?>
<Db xmlns="http://tempuri.org/Db.xsd">
  <DataProcessed>
    <Units>2</Units>
    <PSINIVA>20</PSINIVA>
    <PU>20</PU>
    <Discount>10</Discount>
    <IVA>21</IVA>
    <PCONDT>18</PCONDT>
    <EXENT>0</EXENT>
    <PCONIVA>21.78</PCONIVA>
    <Ivap>7.560000000000002</Ivap>
  </DataProcessed>
  <DataProcessed>
    <Units>1</Units>
    <PSINIVA>100</PSINIVA>
    <PU>100</PU>
    <Discount>0</Discount>
    <IVA>21</IVA>
    <PCONDT>100</PCONDT>
    <EXENT>0</EXENT>
    <PCONIVA>121</PCONIVA>
    <Ivap>21</Ivap>
  </DataProcessed>
</Db>

...which is, I believe, your desired result.

This approach has the added benefit of eliminating the Magic Strings from your code.

  • Related