Link to home
Start Free TrialLog in
Avatar of trevoray
trevoray

asked on

adding a datarow item value through functions

hi, i have the following....

di = dt.NewRow()
di("transid") = strTransID

and then i go down my code and continue to add values to the datarow dependant upon what user has checked in previous panel of form.

the problem is that when i get to one point, my code pulls a function to check to see which checkboxes have been checked (i cannot change this)

so i do this function in my code

confirmationtext = getssvalues(int,ssname)

and then i continue on.

i need to figure out how i can continue to add items to my new row going into the other function. and then coming back out and continue adding values after the function.

the getssvalues function looks something like this"

Function getssvalues(int,ssname)
      for each dr in my datatable
      if mycheckboxname.checked = true then
      label1.text &= "checkbox" & int & " $15"
      end if
      next
End Function

that was just a very basic representation of my function to give you an idea.

what i need to add in the middle of it is...

for each dr in my datatable
      if mycheckboxname.checked = true then
      label1.text &= "checkbox" & int & " $15
      '--------- need to add this --------------------------------------
     
      di("checkbox1") = "15"    

      end if
      next

     
how can i do this? thank you!




Avatar of _TAD_
_TAD_



The simple answer is you can't.  At least not the way your code is now.


di = dt.NewRow()


The line above basically states that you want to create a new row with the exact same column format as in your datatable dt.

Your best option would be to create a new set of columns for a new row that you will pull from your function.  You can then use the data in dataRow2 to populate your initial data row.
Avatar of trevoray

ASKER

i DO want to create a new row with the exact same column forat as in my datatable dt

i want to be able to add the values of this new row across different functions. i have a mulitple-panel form that the user will be going through and i want to add dataitems to this one single new row through all the different panels/functions.

and then once the user has reached the end of the form, my one single row will be complete and then i can finish it off with

dt.rows.add(di)


Ah, I see....


Then what you need to do is make your di declaration a class level declaration so that is can be access in your other functions.

imports System.Data

Dim di as DataRow
...
..
.
private Function doStuff()
    di = dt.NewRow()

end func

private function OtherFunction()

di("checkbox") = true
end function
Or build a resursive function (a function that calls itself untill done)...
ok, i added the di=datarow to the class level declaration, and it now lets me add rows values across functions, but IT WILL NOT let me continue adding row values after any postbacks.  

roverm, is resursive function the only way to accomplish this? if so, how? since i've never even heard the word resursive before, i am assuming i will need MUCH hand holding.  :)

everything works beautifully so far, EXCEPT after i press submit to go to next panel, then I get a null error when i try to add to the datarow. any quick fix around this?

thanks!
Sorry, misread it. No, the recursive function will NOT accomplish that.
What you could do is store the result in the ViewState and read it back in the postback.
also, for clarification, this is the statement that i added to the class level that allows me to now add row values across functions, but does not allow me to add values after postback...

 Dim dt As New DataTable("duesTable")
    Dim di As DataRow


do i have to somehow show my code what datatable i am calling after postback? somehow "point" to it?
and if it is simply not possible to add datarow values to a datatable after postback, then i guess i will have to complete the datatable before postback, but then on postback i will have to change some of the datatable values.  this would be my last resort. if this is the option i must follow, then how would i access my datatable after postback to change some of the values?

thanks!
It can be done:
Public declaration:


    Private dt As DataTable


Then in you page_load event:

        If Not IsPostBack Then
            dt = New DataTable("mytablename")
            With dt
                .Columns.Add("field1")
                .Columns.Add("field2")
                .Columns.Add("field3")
                .Columns.Add("field4")
            End With
            Dim arr() As String = Split("1,2,3,4", ",")
            dt.Rows.Add(arr)
            ViewState.Add("mytable", dt)
        Else
            dt = ViewState("mytable")
            Response.Write("# of rows:" & dt.Rows.Count)
        End If

D'Mzz!
RoverM
So, if the page is first loaded (not ispostback) then you will create the table and store it in the viewstate.
If it is a postback then just grab it from the viewstate.

D'Mzz!
RoverM
ok, in the code:

ViewState("mytable", dt)

can "mytable" be any value, am i defining the name of the viewstate here, or does it need to be the name of my table?
It can be whatever you want!
It's just a pointer (key) to your table in the viewstate.
This pointer you will use to retrieve the table from the viewstate.

So, you can name it anyway you'd like. I would suggest your table's name.

D'Mzz!
RoverM
ok, here's the next part. in my code i am using the syntax below to add values, i am adding values individually and not an array..

Dim di as DataRow

di("dues_year") = "2004"

using the above format, now would i continue to add row item values to my datatable?

thanks!
You have to create a newrow for that table first using dt.NewRow():

        If Not IsPostBack Then
            dt = New DataTable("mytablename")
            With dt
                .Columns.Add("field1")
                .Columns.Add("field2")
                .Columns.Add("field3")
                .Columns.Add("field4")
            End With
            Dim arr() As String = Split("1,2,3,4", ",")
            dt.Rows.Add(arr)
            ViewState.Add("mytable", dt)
        Else
            dt = ViewState("mytable")
            Response.Write("# of rows before update:" & dt.Rows.Count)
            Dim rw As DataRow = dt.NewRow()
            With rw
                .Item("field1") = "value1"
                .Item("field2") = "value2"
                .Item("field3") = "value3"
                .Item("field4") = "value4"
            End With
            dt.Rows.Add(rw)
            Response.Write("# of rows after update:" & dt.Rows.Count)
        End If


D'Mzz!
RoverM
ok, that's the deal, i don't want to create a new row. i want to be able to add row values through to my datatable gradually, and then like so..

        Sub PageLoad()
        Dim dt As New DataTable("duesTable")
             With dt
            .Columns.Add("transid")
            .Columns.Add("nmmst_id")
            .Columns.Add("dues_year")
            .Columns.Add("firstname")
            .Columns.Add("lastname")
            .Columns.Add("complete")
            End With

        Dim di As DataRow
        di = dt.NewRow()
        di("transid") = strTransID
        di("nmmst_id") = Label6.Text
        di("dues_year") = "2003"
        doSomething()

        ViewState("mytable", dt)
        End Sub

        Function doSomething()
        di("firstname") = "Trevor"
        End Function


        '------------ all the above currently works------------

        ' i want to do this...

      Sub onButton1_Click(e as event....)
      dt = ViewState("mytable")
      di("lastname") = "Smith"
      di("complete") = "Yes"
      dt.Rows.Add(di)
      End Sub



Ok, so you want to update that particular row on every postback?

Just don't add the row to the table but store it in the viewstate.

So: (didn't test this, could be typo's in it)

Sub Button1_Click(.....)
    dt = ViewState("mytable")
    Dim rw As DataRow = ViewState("mydatarow")
    rw.Item("lastname") = "Smith"
    dt.Rows.Add(rw)
End Sub

And in the postback event store it into the viewstate:

    ViewState.Add("mydatarow", rw)

D'Mzz!
RoverM
i'm guessing this is not possible? to have an incomplete row before i do the postback, and then after the postback, finish up adding to the row values and then to add the row to the datatable?
Didn't my last example work?
i actually tried that earlier and am getting this error:

Server Error in '/dotnet' Application.
The type 'System.Data.DataRow' must be marked as Serializable or have a TypeConverter other than ReferenceConverter to be put in viewstate.

this was what i used, it was the last part of the imcomplete row addition before moving on to the next panel..


        di("total_paid") = Label10.Text

        ViewState.Add("duestable", dt)
        ViewState.Add("duesrow", di)

it gave me the above error.
Then you will have to parse it to an array first:

        If Not IsPostBack Then
            dt = New DataTable("mytablename")
            With dt
                .Columns.Add("field1")
                .Columns.Add("field2")
                .Columns.Add("field3")
                .Columns.Add("field4")
            End With
            Dim arr() As String = Split("1,2,3,4", ",")
            dt.Rows.Add(arr)
            ViewState.Add("mytable", dt)
        Else
            dt = ViewState("mytable")
            Response.Write("# of rows before update:" & dt.Rows.Count & "<br>")
            Dim temparr As Array
            Dim rw As DataRow = dt.NewRow()
            If Not IsNothing(ViewState("test")) Then
                temparr = ViewState("test")
                rw.ItemArray = temparr
                With rw
                    .Item("field3") = "value3"
                    .Item("field4") = "value4"
                    dt.Rows.Add(rw)
                End With
            Else
                With rw
                    .Item("field1") = "value1"
                    .Item("field2") = "value2"
                End With
            End If
            Dim arr As Array = rw.ItemArray
            ViewState.Add("test", arr)
            Response.Write("# of rows after update:" & dt.Rows.Count & "<br>")
        End If

I've tested this ;-)
Whoops, forgot my explanation:

In the first time postback the ViewState("test") will be nothing.
Then the fields "field1" and "field2" will be filled.

After converting the row to an array the viewstate("test") is stored.

The second time postback the ViewState("test") will exist.
It will be retrieved into an array (temparr) and temparr is used to put it into the row.

Then fields "field3" and "field4" are filled and stored into the table.
ok, i don't think i want to do it that way. i would really like to keep my existing format. so, knowing that i cannot do what i explained above, can i do this?

i will add the row before postback, save the table in viewstate to access later, then i want to edit one of the row values, how can i after postback edit the "submit_date" column for all rows?
sorry for being so picky, i just spent a lot of time doing in one format and would like to keep that code if possible. and especially since i really am only needing to change one value after postback, it doesn't seem worth to rewrite my code for that.
Why not? :-)

It's obvious that you can't store the datarow in the ViewState.

But why are you doing it this way?
Why not store it in SQL Server on the first postback, readback the RowID, store the RowID in the viewstate and on the second postback readback that RowID from the Viewstate and update SQL Server with the missing value.

'The datarow is a object while viewstate only stores basic data types. YOu will need convert it to a format viewstate can understand.
'I modified a little bit of your code to store the value in string and create the datatable when it is finished collecting all the necessary value in viewstate.
       Sub PageLoad()
        viewstate("transid") = strTransID
        viewstate("nmmst_id") = Label6.Text
        viewstate("dues_year") = "2003"

         doSomething()

        End Sub

        Function doSomething()
        viewstate("firstname") = "Trevor"
        End Function


        '------------ all the above currently works------------

        ' i want to do this...

      Sub onButton1_Click(e as event....)
       Dim dt As New DataTable("duesTable")
             With dt
            .Columns.Add("transid")
            .Columns.Add("nmmst_id")
            .Columns.Add("dues_year")
            .Columns.Add("firstname")
            .Columns.Add("lastname")
            .Columns.Add("complete")
            End With

        Dim di As DataRow
        di = dt.NewRow()
       di("transid") = viewstate("transid")
        di("nmmst_id") =  viewstate("nmmst_id")
        di("dues_year") = viewstate("dues_year")
        di("firstname") =viewstate("firstname")
       di("lastname")= "Smith"
      di("complete") = "Yes"
      End Sub
because there will be multiple rows and multiple row id's.  and if the credit card transaction fails, i do  not want a record stored in SQL server.

so, if i know the exact number of the column that i want to edit, i think i can do this...  ??

dt = ViewState("duestable")
Dim dr as DataRow
For each dr in dt

dt.Rows.Item(49) = Now

Next

explanation: where 49 is the 49th column of my datatable (my submit_date column)

would this work? is that correct syntax?
or actually maybe this would work better?

    dt = ViewState("duestable")
        Dim dr As DataRow
        Dim int As Integer
        int = -1
        For Each dr In dt.Columns
            int = int + 1
            dt.Rows(int).Item(49) = Now
        Next
ASKER CERTIFIED SOLUTION
Avatar of roverm
roverm
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ok, i modified my code to below and it worked!! it gave me exactly the result i was trying to achieve. thanks for all your help!

dt = ViewState("duestable")
        Dim drn As DataRow
        Dim int As Integer
        int = -1
        For Each drn In dt.Rows
            int = int + 1
            dt.Rows(int).Item(49) = Now
        Next


good answer rover!


as for a recursive function (you mentioned you had never heard of one before), they are extremely useful when trying to walk a directory structure.

In a nutshell, a recursive function is a function that calls itself.

Here is a simple recursive function (pretty much useless, but easy to understand)


Dim x as Integer
x=1

x = recurFunc(x)

Console.WriteLine(x.ToString())


private function recurFunc(byVal i as Integer)

i = i + 1

if i<10 Then
   i = recurFunc(i)

return i

end Function



<---------------------->
If you were to step through the function

x = 1
i = 1
i = 2
Call func
i = 3
Call func
i = 4
Call func
i = 5
Call func
i = 6
Call func
i = 7
Call func
i = 8
Call func
i = 9
Call func
i = 10
return i ( which equals 10)
return i ( which equals 10)
return i ( which equals 10)
return i ( which equals 10)
return i ( which equals 10)
return i ( which equals 10)
return i ( which equals 10)
return i ( which equals 10)
return i ( which equals 10)
x = 10
Little shorter:
For each drw As DataRow In dt.Rows
    drw.Item(49) = Now
Next

You won't have to use the integer.

Thanks for the points!

D'Mzz!
RoverM


Obviously this example is pretty useless, but if you were to search a directory tree for all files and folders of a given directory.


This function is written in C#, but I think it is basic enough to understand even if you don't know C#


            private void button3_Click(object sender, System.EventArgs e)
            {
                  RecurFunc(@"C:\temp");

            }

            private void RecurFunc(string path)
            {
                  string[] dir = Directory.GetDirectories(path);
                  string[] file = Directory.GetFiles(path);
                  
                  for(int i=0;i<file.Length;i++)
                        Console.WriteLine(file[i]);

                  for(int i=0;i<dir.Length;i++)
                        RecurFunc(dir[i]);
            }