populating Crystal Reports from DataGrid data

B

Brock

I am trying to populate a Crystal Report from data in my DataGrid. The
reason for this is that I want the user to be able to change values
without updating the database, but still have their report reflect the
values they anticipate committing to see hypothetical totals of
columns from a set of records. These records are displaying properly
on my DataGrid but I'm not sure how to get Crystal Reports 10 to use
as its datasource the dataset in memory that could be had directly
from the datagrid.

I'm guessing I need to Dim a new DataSet, populate it from the
datagrid, and set the new dataset as the datasource for CR. But how?

How can I specify that the Datagrid's DataSource property can be
explicitly cast as a DataSet object that CR can pick up. And how in CR
do I tell it that this resultingDataSet is what it needs for the
report?

I found a snippet of code that may work as PART of the solution, but I
need a little direction.
Private Sub FillDataSet(ByVal DataFromGrid As DataSet)
DataFromGrid = CType(dgEmployees.DataSource, DataSet)
End Sub
 
B

Brock

I tried to adapt your method, well I should say I got totally lost in
the process. Back to your reply, ad I do appreciate the help:

"I would go with the PUSH method of CR (crystal report) development.
And instead of worrying about the datagrid as the SOURCE, cache
(session?)
the dataset (or datatable possibly) and use it as the source for the
datagrid AND then the report."

I went into my report to use the CR DatabaseExpert and stumbled when
trying to decide what to put in for my datasource. My datasource for
the datagrid itself gets populated with this code:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
'lblWelcome.Text = "Hello " & Global.UserSecurity.Fname.Trim &
" " & Global.UserSecurity.Lname
Dim act As Action
Dim pos As Position
Dim empname As String
Dim lvi As ListItem
Dim Employee As Employee
Dim empcount As Integer
act = (New
ActionBroker).GetActionCurrent(Global.UserSecurity.EmpId, Today,
Global.UserName, Global.UserPassword, Global.appDataSource)
pos = (New PositionBroker).GetPosition(act.PositionID,
Global.UserName, Global.UserPassword, Global.appDataSource)
m_department = pos.Department.Name
Dim emps As Employees = (New
EmployeeBroker).GetCurrentEmployeesByDepartment(m_department,
Global.UserName, Global.UserPassword, Global.appDataSource)
Dim dt As New DataTable
Dim count As Integer = 0
For Each emp As Employee In emps
SetListViewItem(emp, dt, count)
count = count + 1
Next
dgEmployees.DataSource = dt
dgEmployees.DataBind()
End Sub
Private Sub SetListViewItem(ByVal dr As Employee, ByVal dt As
DataTable, ByVal count As Integer)
If count = 0 Then
dt.Columns.Add("Emp #")
dt.Columns.Add("Last Name")
dt.Columns.Add("First Name")
dt.Columns.Add("Title")
End If
Dim EmpPos As Action = (New
ActionBroker).GetActionCurrent(dr.Key, Today, Global.UserName,
Global.UserPassword, Global.appDataSource)
Dim employee As DataRow = dt.NewRow
employee("Emp #") = dr.Key
employee("Last Name") = dr.LastName

employee("First Name") = dr.FirstName
employee("Title") = EmpPos.WorkAgainstInfo.Title
dt.Rows.Add(employee)
End Sub 'SetListViewItem

The immediate challenge is that the datasource I was given by the
powers that be was a precompiled DLL with stored procedures and
database connections made to an Oracle database. So I didn't know the
foggiest idea of how the above code could be adapted/used to provide
CR with its data needs. I thought it might be in this specific case
more manageable for this newbie to find a way of using the datagrid as
the CR source (not that I know how to approach that either). But I can
see the challenges with caching and viewstate in a more complex page
than what I'm doing.

So any clues would be great... thanks! Brockus
 
S

sloan

Ok, since you're in a web world...you gotta keep some stuff straight.

Your attempt to "re-get" the DataSource ~from~ the DataGrid after the page
is rendered is not a good strategy.


You also need to remember that once a page displays, alot of things you had
in the code behind are not there anymore, unless you specifically save them
somewhere.
(Like the Session as the usual suspect).


So I will outline something that I think is the correct approach.


On the page_load........
Populate your source data (dataset) however you normally do this. I
will call this the model from now on.
Put the model in the Session object using a unique keyname.
Bind the model to the DataGrid you have on the page already.

You now have two things:
1. The original data inside the Session object.
2. A ~display~ of the original data on the user's browser.

The user makes changes.

Now you need to COLLECT the information the user changed by iterating
over all the rows in the datagrid, and pulling out the values.
Tip: Use a hidden object for those pieces of information you don't
want to display, but want to keep around.
Put this data into a new dataset (a new "model").
You can throw this into the Session object as well (if you want to) with
a DIFFERENT key name.

Optional:
Use the model(1) and the model(2) and create a massaged version of
the data.

Take the new model , and use the PUSH method to populate the Crystal
Report.



PS
You should be able to bind the datagrid aganst this object
Dim emps As Employees
without artificially converting it to a dataset/datatable. Have you tried
this yet?




I tried to adapt your method, well I should say I got totally lost in
the process. Back to your reply, ad I do appreciate the help:

"I would go with the PUSH method of CR (crystal report) development.
And instead of worrying about the datagrid as the SOURCE, cache
(session?)
the dataset (or datatable possibly) and use it as the source for the
datagrid AND then the report."

I went into my report to use the CR DatabaseExpert and stumbled when
trying to decide what to put in for my datasource. My datasource for
the datagrid itself gets populated with this code:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
'lblWelcome.Text = "Hello " & Global.UserSecurity.Fname.Trim &
" " & Global.UserSecurity.Lname
Dim act As Action
Dim pos As Position
Dim empname As String
Dim lvi As ListItem
Dim Employee As Employee
Dim empcount As Integer
act = (New
ActionBroker).GetActionCurrent(Global.UserSecurity.EmpId, Today,
Global.UserName, Global.UserPassword, Global.appDataSource)
pos = (New PositionBroker).GetPosition(act.PositionID,
Global.UserName, Global.UserPassword, Global.appDataSource)
m_department = pos.Department.Name
Dim emps As Employees = (New
EmployeeBroker).GetCurrentEmployeesByDepartment(m_department,
Global.UserName, Global.UserPassword, Global.appDataSource)
Dim dt As New DataTable
Dim count As Integer = 0
For Each emp As Employee In emps
SetListViewItem(emp, dt, count)
count = count + 1
Next
dgEmployees.DataSource = dt
dgEmployees.DataBind()
End Sub
Private Sub SetListViewItem(ByVal dr As Employee, ByVal dt As
DataTable, ByVal count As Integer)
If count = 0 Then
dt.Columns.Add("Emp #")
dt.Columns.Add("Last Name")
dt.Columns.Add("First Name")
dt.Columns.Add("Title")
End If
Dim EmpPos As Action = (New
ActionBroker).GetActionCurrent(dr.Key, Today, Global.UserName,
Global.UserPassword, Global.appDataSource)
Dim employee As DataRow = dt.NewRow
employee("Emp #") = dr.Key
employee("Last Name") = dr.LastName

employee("First Name") = dr.FirstName
employee("Title") = EmpPos.WorkAgainstInfo.Title
dt.Rows.Add(employee)
End Sub 'SetListViewItem

The immediate challenge is that the datasource I was given by the
powers that be was a precompiled DLL with stored procedures and
database connections made to an Oracle database. So I didn't know the
foggiest idea of how the above code could be adapted/used to provide
CR with its data needs. I thought it might be in this specific case
more manageable for this newbie to find a way of using the datagrid as
the CR source (not that I know how to approach that either). But I can
see the challenges with caching and viewstate in a more complex page
than what I'm doing.

So any clues would be great... thanks! Brockus
 
B

Brock

My apologies, but I'm a real newbie on several key issues. One is how
to access the "Session" and again how to specify in CR itself what its
datasource is.
 
B

Brock

Hi Sloan... another poster on 'microsoft.public.dotnet.languages.vb'
suggested using something like:

MyCrystalReport.SetDataSource(MyDataGrid.DataSource)

- to set the CR datasource... I'm guessing placing that in my code-
behind .aspx.vb (?) - maybe in the event handler for a button that
displays the reportViewer?
If that's the case would I go into the CR Datasource wizard and spell-
out something to let CR know this is where to look? My CR I'm writing
resides as an object in the actual project, but I don't know how much
CR recognizes datasources and how explicit the location needs to
read... thanks! Brockus
 
S

sloan

I know he drilled you about it already....but I'll throw another reminder

"another poster on 'microsoft.public.dotnet.languages.vb'
suggested using something like:"

That's why multi posting stinks, because you get disjoint conversations
going.
So we'll let this ~one~ slide.

...

You'll have to experiment with the syntax he gave you.

...

However. You need to list out what is happening as regards to
page-life-time.

Are you trying to populate the datagrid and the CR on the same page request?

Or are you trying to populate the datagrid on one page request....and the CR
on another (second) page request.

If the latter, then I'm still in favor of what I told you before...about
putting the (populated) dataset into Session memory.

...

I know you're a newbie, at the same time, the most basic concepts you need
to get straight are:

1. Lifetime/cycle of a single page request.
2. How to put objects (like your populated dataset object) into the Session
object.

...


Hi Sloan... another poster on 'microsoft.public.dotnet.languages.vb'
suggested using something like:

MyCrystalReport.SetDataSource(MyDataGrid.DataSource)

- to set the CR datasource... I'm guessing placing that in my code-
behind .aspx.vb (?) - maybe in the event handler for a button that
displays the reportViewer?
If that's the case would I go into the CR Datasource wizard and spell-
out something to let CR know this is where to look? My CR I'm writing
resides as an object in the actual project, but I don't know how much
CR recognizes datasources and how explicit the location needs to
read... thanks! Brockus
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top