How to pass parameter value to crystal report's data source - vb.net

i got a stored procedure and i got it going in my crystal report
CREATE FUNCTION [dbo].[SP_MainContent]
( #from int,
#to int,
#year int,
#office varchar(MAX),
#fund varchar(MAX)
)
RETURNS TABLE
AS
RETURN (
SELECT AccntTbl.Id,
AccntTbl.accnt,
ISNULL(SupplyTbl.Supply, 0) AS Supply,
AccntTbl.office,
AccntTbl.exp,
AccntTbl.dateCreated
FROM AccntTbl
LEFT JOIN
(SELECT idAccnt,
SUM(amount) AS Supply
FROM SuppyTbl AS SupplyTbl1
WHERE MONTH(dateCreated) BETWEEN #from AND #to
AND YEAR(dateCreated) = #year
AND fund = #fund
GROUP BY idAccnt) AS SupplyTbl
WHERE YEAR(AccntTbl.dateCreated) = #year
AND AccntTbl.office = #office
AND AccntTbl.fund = #fund
GROUP BY AccntTbl.Id,
AccntTbl.accnt,
AccntTbl.appro,
Supply.Supply
);
and in VB.NET
Dim ad As New SqlDataAdapter("SP_MainContent '" & 1 & "', '" & 2 & "', '" & 2016 & "', " & _
" 'office', 'food'", conn)
Dim ds As New DataSet
Dim rpt As New CRreport
ad.Fill(ds, "SP_MainContent")
rpt.SetDataSource(ds)
CrystalReportViewer1.Refresh()
CrystalReportViewer1.ReportSource = rpt
but every time i open up the report this window will pop-up, its is so annoying.
how to stop this to pop up ? whenever i open up my report in vb.net
glad for any help..tnx :)

You should pass parameter values like below
rpt.SetParameterValue("#param_name", the_value)

Related

MS Access VBA multiple list box search form

I have a requirement to allow a user to search between two dates on a form and filter the data down further using multiple list boxes
Currently I allow the user to search between a from and to date... And also filter by products from a listbox.
If no products are selected in the list box, only display the results of the query between the two dates.
If the selection critera of the listbox is not empty, build the query WHERE with IN clause and then concanenate it to the SELECT statement, then execute the query to give desired results.
My question is... How would I do this for another four or five multi value list boxes? For example: Suppliers, Depots, Countries, Varieties etc etc
SearchAllReject is simply a function to query from and to date with no product filters.
Here is the code I already have:
Dim SQLAllReject As String
Dim strDateFrom As String
Dim strDateTo As String
Dim strFirstDate As Date
Dim strSecondDate As Date
Dim strINPRODUCT As String
Dim strWHERE As String
Dim strSTRING As String
Dim i As Integer
If Len(Me.txtDate.Value & vbNullString) = 0 Then
MsgBox ("Please input date from")
Exit Sub
ElseIf Len(Me.txtDateTo.Value & vbNullString) = 0 Then
MsgBox ("Please input date to")
Exit Sub
End If
strDateFrom = txtDate.Value
strDateTo = txtDateTo.Value
strFirstDate = Format(CDate(strDateFrom), "mm/dd/yyyy")
strSecondDate = Format(CDate(strDateTo), "mm/dd/yyyy")
For i = 0 To lstProduct.ListCount - 1
If lstProduct.Selected(i) Then
strINPRODUCT = strINPRODUCT & "'" & lstProduct.Column(1, i) & "',"
End If
Next i
If Len(strINPRODUCT & vbNullString) = 0 Then
SearchAllReject
Else
strWHEREPRODUCT = "AND dbo_busobj_file_rejections_load_temp5.Tesco_Product_Name IN " & _
"(" & Left(strINPRODUCT, Len(strINPRODUCT) - 1) & "))"
SQLAllReject = "SELECT dbo_busobj_file_rejections_load_temp5.Reject_Date AS [Date], " & _
"dbo_busobj_file_rejections_load_temp5.Depot_Number AS [Depot No], " & _
"dbo_busobj_file_rejections_load_temp5.Depot_Name AS [Depot], dbo_busobj_file_rejections_load_temp5.Tesco_Product_Name AS [Product]," & _
"dbo_busobj_file_rejections_load_temp5.Tesco_Brand_Name AS [Brand], dbo_busobj_file_rejections_load_temp5.Tesco_Packsize AS [Packsize], " & _
"dbo_busobj_file_rejections_load_temp5.TPNB, dbo_busobj_file_rejections_load_temp5.EAN, " & _
"dbo_busobj_file_rejections_load_temp5.Tesco_Country_of_Origin AS [Country], " & _
"dbo_busobj_file_rejections_load_temp5.Tesco_Variety AS [Variety], dbo_busobj_file_rejections_load_temp5.Tesco_Producer AS [Producer], " & _
"dbo_busobj_file_rejections_load_temp5.reject_qty AS [Quantity], dbo_busobj_file_rejections_load_temp5.batch_code AS [Batch Code], " & _
"dbo_busobj_file_rejections_load_temp5.site AS [Site], dbo_busobj_file_rejections_load_temp5.Tesco_Comment AS [Comment], " & _
"dbo_busobj_file_rejections_load_temp5.Tesco_Reason AS [Reason] " & _
"FROM dbo_busobj_file_rejections_load_temp5 " & _
"WHERE (((dbo_busobj_file_rejections_load_temp5.Reject_Date) Between #" & strFirstDate & "# And #" & strSecondDate & "#) "
strSTRING = SQLAllReject & strWHEREPRODUCT
Debug.Print strSTRING
Me.lstDeleteReject.RowSource = strSTRING
Me.lstDeleteReject.Requery
Consider building an entity-attribute table of all possible listbox values and use a saved SQL query which avoids any messy concatenation of SQL in VBA. A parameterized query using QueryDef is used to update the selected options of table of all list box values.
Table (myListBoxValues) (built once and updated with new values/categories)
Category|Value |Selected
--------|----------|--------
Product |Product A | 1
Product |Product B | 1
Product |Product C | 1
...
Country |USA | 1
Country |Canada | 1
Country |Japan | 1
Above can be populated with multiple append queries using SELECT DISTINCT:
INSERT INTO myListBoxValues ([Category], [Value], [Selected])
SELECT DISTINCT 'Product', Tesco_Product_Name, 1
FROM dbo_busobj_file_rejections_load_temp5 b
NOTE: It is very important to default all Selected to 1 for VBA purposes. See further below. Also, if you have a mix of number and string, consider using TextValue and NumberValue columns and adjust in SQL IN clauses. Save above query as a new object and place the named object behind target: lstDeleteReject.
SQL (built once, adjust form name)
Notice the form date values are directly incorporated into WHERE clause without any date formatting conversion or concatenation needs. Also, table alias is used to avoid long name repetition.
SELECT b.Reject_Date AS [Date],
b.Depot_Number AS [Depot No],
b.Depot_Name AS [Depot], b.Tesco_Product_Name AS [Product],
b.Tesco_Brand_Name AS [Brand], b.Tesco_Packsize AS [Packsize],
b.TPNB, b.EAN,
b.Tesco_Country_of_Origin AS [Country],
b.Tesco_Variety AS [Variety], b.Tesco_Producer AS [Producer],
b.reject_qty AS [Quantity], b.batch_code AS [Batch Code],
b.site AS [Site], b.Tesco_Comment AS [Comment],
b.Tesco_Reason AS [Reason]
FROM dbo_busobj_file_rejections_load_temp5 AS b
WHERE b.Reject_Date BETWEEN Forms!myFormName!txtDate
AND Forms!myFormName!txtDateTo
AND b.Tesco_Product_Name IN (
SELECT [Value] FROM myListBoxValues
WHERE [Category] = 'Product' AND [Selected] = 1
)
AND b.site IN (
SELECT [Value] FROM myListBoxValues
WHERE [Category] = 'Site' AND [Selected] = 1
)
AND b.Tesco_Producer IN (
SELECT [Value] FROM myListBoxValues
WHERE [Category] = 'Producer' AND [Selected] = 1
)
AND b.Depot_Name IN (
SELECT [Value] FROM myListBoxValues
WHERE [Category] = 'Depot' AND [Selected] = 1
)
AND b.Tesco_Country_of_Origin IN (
SELECT [Value] FROM myListBoxValues
WHERE [Category] = 'Country' AND [Selected] = 1
)
VBA (adjust list box names to actuals)
Dim qdef As QueryDef
Dim lstname As Variant
Dim sql As String
Dim i As Integer
sql = "PARAMETERS paramValue TEXT, paramCateg INTEGER; " _
& "UPDATE myListBoxes SET [Selected] = 0 " _
& "WHERE [Value] = paramValue AND [Category] = paramCateg"
Set qdef = CurrentDb.CreateQueryDef("", sql)
' ITERATE THROUGH ALL LISTBOXES BY NAME
For Each lstname in Array("lstProduct", "lstSite", "lstProducer", "lstDepot", "lstCountry")
For i = 0 To Me.Controls(lstname).ListCount - 1
' UPDATE IF AT LEAST ONE ITEM IS SELECTED
If Me.Controls(lstname).ItemsSelected.Count > 0
' UPDATE [SELECTED] COLUMN TO ZERO IF VALUES ARE NOT SELECTED
If Me.Controls(lstname).Selected(i) = False Then
qdef!paramValue = Me.Controls(lstname).Value
qdef!paramCategory = Replace(lstName, "lst", "")
qdef.Execute
End If
End If
Next i
Next lstname
Set qdef = Nothing
' REQUERY LISTBOX
Me.lstDeleteReject.Requery
' RESET ALL SELECTED BACK TO 1
CurrentDb.Execute "UPDATE myListBoxValues SET [Selected] = 1"
As you can see, much better readability and maintainability. Also, if users do not select any option, the date range filters are still applied and using your universal table of all list box values, all values will be selected to returns all non-NULL values.

Dynamic Calculated Field in VBA Access

I'm trying to add a field into an existing table. The field is calculated using two variables 'myPrice', which is the price of a record at a certain date, and 'previousPrice', which is the price of the same part from the first record, only a from the month previous. I'm using a loop to iterate through the entire recordset of prices, thereby altering the two variables each time. My code is as follows:
Function priceDifference()
Dim currentPrice As Currency
Dim previousPrice As Currency
Dim recordDate As Date
Dim previousDate As Date
Dim dbsASSP As DAO.Database
Dim priceTable As DAO.TableDef
Dim diffFld As DAO.Field2
Dim rstCurrentPrice As DAO.Recordset
Dim rstPreviousPrice As DAO.Recordset
Dim PN As String
Set dbsASSP = CurrentDb
strSQL = "SELECT * FROM qryPrice"
Set rstCurrentPrice = dbsASSP.OpenRecordset(strSQL, dbOpenDynaset)
Set priceTable = dbsASSP.TableDefs("tblPrice")
Set diffFld = priceTable.CreateField("Difference", dbCurrency)
If Not (rstCurrentPrice.EOF) Then
rstCurrentPrice.MoveFirst
Do Until rstCurrentPrice.EOF = True
PN = rstCurrentPrice![P/N]
recordDate = rstCurrentPrice![myDate]
previousDate = Format(DateAdd("m", -1, recordDate), "M 1 YYYY")
myPrice = rstCurrentPrice!Price
strPreviousSQL = "SELECT * FROM qryPrice WHERE [MyDate] = #" & previousDate & "# AND [Type] = 'Net Price' AND [P/N] = " & PN & ""
Set rstPreviousPrice = dbsASSP.OpenRecordset(strPreviousSQL, dbOpenDynaset)
myCodeName = rstCurrentPrice!CodeName
If DCount("[P/N]", "qryPrice", "[MyDate] = #" & previousDate & "# And [P/N] = " & PN) <> 0 Then
previousPrice = rstPreviousPrice!Price
Else
previousPrice = myPrice
End If
rstCurrentPrice.MoveNext
Loop
Else
MsgBox "Finished looping through records."
End If
diffFld.Expression = myPrice - previousPrice
rstCurrentPrice.Close
rstPreviousPrice.Close
priceTable.Fields.Append diffFld
End Function
Syntactically, it works. The calculated field, however, does not give me the correct values and I cannot figure out why, although I imagine it has something to do with the dynamic formula.
Any help is appreciated. Thanks!!
Your code can't work as you append a number to the field instead of a formula, but you should avoid calculated fields
Use a query:
SELECT
nPrice.[P/N],
nPrice.Price,
nPrice.MyDate,
oPrice.MyDate,
nPrice.Price-Nz(oPrice.Price,nPrice.Price) AS diff
FROM (
SELECT
[P/N],
Price,
MyDate,
Format(DateAdd("m",-1,MyDate),"yyyymm") as previousMonthYear
FROM
tblPrice) AS nPrice
LEFT JOIN (
SELECT
[P/N],
Price,
MyDate,
Format(MyDate,"yyyymm") AS monthYear
FROM
tblPrice) AS oPrice
ON
nPrice.[P/N] = oPrice.[P/N]
AND nPrice.previousMonthYear = oPrice.monthYear
This calculates the difference dynamic and you don't need to store it.
I assume there is max one price per month, otherwise you need to filter the subqueries or just calculate the difference to the last price before.
If the query is too slow ([P/N] and MyDate need an index) , you can still use it to update a field the table tblPrice, but this has to be updated every time a price is updated or inserted in tblPrice
I think you can avoid your code loop by using this query
SELECT A.qryPrice, A.MyDate, B.qryPrice, B.MyDate
FROM qryPrice A LEFT OUTER JOIN qryPrice B
ON A.[P/N] = B.[P/N]
AND B.MyDate = DATEADD(month, -1, A.MyDate)

Merge query from datagridview to database not executing sql, vb.net

I'm having a problem executing a merge query from to update or insert values from a DataGridView table into a sql server database table. Here is my code below, it doesn't give me any errors or stoppages, however I recently noticed that it has been creating completely rows in my database table dbo.schedule which contain all NULL values even that key location, could someone please help me? I'm not very familiar with merge queries in sql so please point out issues with my syntax:
Dim query As String = String.Empty
query &= "DECLARE #TaskID nvarchar(8), #Task nvarchar(50), #Start_date datetime, #Due_date datetime, #Complete bit, #Task_Manager nvarchar(8), #JRID nvarchar(10), #Entered_By char(50), #Time_Entered datetime;"
query &= "MERGE INTO schedule USING (VALUES (#TaskID, #Task, #start_date, #Due_Date, #Complete, #Task_Manager, #JRID, #Entered_By, #Time_Entered)) AS t(TaskID, Task, start_date, Due_Date, Complete, Task_Manager, JRID, Entered_By, Time_Entered) "
query &= "ON schedule.TaskID = #TaskID WHEN MATCHED THEN"
query &= " UPDATE SET schedule.TaskID = t.TaskID, schedule.Task=t.Task, schedule.start_date=t.start_date, schedule.due_date=t.due_date, schedule.complete=t.complete, schedule.task_manager=t.task_manager, "
query &= "schedule.JRID=t.JRID, schedule.Entered_by=t.Entered_by, schedule.Time_Entered=t.Time_Entered"
query &= " WHEN NOT MATCHED THEN INSERT (TaskID, Task, start_date, Due_Date, Complete, Task_Manager, JRID, Entered_By, Time_Entered)"
query &= " VALUES (#TaskID, #Task, #start_date, #Due_Date, #Complete, #Task_Manager, #JRID, #Entered_By, #Time_Entered);"
Using conn As New SqlConnection(dbLocations(0, 1))
Using comm As New SqlCommand()
With comm
For Each row As DataGridViewRow In MainSchedule.DataGridView1.Rows
If Not (row.Cells(0).Value = Nothing) Then
.Parameters.Clear()
.Connection = conn
.CommandType = CommandType.Text
.CommandText = query
insertcommand.Parameters.AddWithValue("#TaskID", TNn)
insertcommand.Parameters.AddWithValue("#Complete", "False")
insertcommand.Parameters.AddWithValue("#Task", row.Cells(0).Value)
insertcommand.Parameters.AddWithValue("#Start_date", row.Cells(1).Value)
insertcommand.Parameters.AddWithValue("#Due_Date", row.Cells(2).Value)
insertcommand.Parameters.AddWithValue("#JRID", txtJRID.Text)
insertcommand.Parameters.AddWithValue("#Task_Manager", row.Cells(3).Value)
insertcommand.Parameters.AddWithValue("#Entered_By", GetUserName())
insertcommand.Parameters.AddWithValue("#Time_Entered", Now)
NextTask()
End If
Next
End With
conn.Open()
comm.ExecuteNonQuery()
End Using
End Using
I figured it out in case anyone is wondering, here is my new code:
Connexion.Open()
Dim query As String = String.Empty
Dim keypos = 0
query &= "UPDATE schedule SET Task = #Task, Complete = #Complete, Start_date = #Start_date, "
query &= "Due_date = #Due_date, JRID = #JRID, Task_Manager = #Task_Manager, Entered_By = #Entered_By, Time_Entered = #Time_Entered "
query &= "WHERE TaskID = #TaskID "
query &= "IF ##ROWCOUNT = 0 INSERT INTO schedule ( TaskID, Task, start_date, Due_Date, Complete, Task_Manager, JRID, Entered_By, Time_Entered)"
query &= " VALUES ( #TaskID, #Task, #start_date, #Due_Date, #Complete, #Task_Manager, #JRID, #Entered_By, #Time_Entered);"
For Each row As DataGridViewRow In MainSchedule.DataGridView1.Rows
If Not (row.Cells(0).Value = Nothing) Then
insertcommand.Parameters.Clear()
insertcommand.CommandText = query
insertcommand.Parameters.AddWithValue("#TaskID", row.Cells(0).Value)
insertcommand.Parameters.AddWithValue("#Complete", "False")
insertcommand.Parameters.AddWithValue("#Task", row.Cells(1).Value)
insertcommand.Parameters.AddWithValue("#Start_date", row.Cells(2).Value)
insertcommand.Parameters.AddWithValue("#Due_Date", row.Cells(3).Value)
insertcommand.Parameters.AddWithValue("#JRID", txtJRID.Text)
insertcommand.Parameters.AddWithValue("#Task_Manager", row.Cells(4).Value)
insertcommand.Parameters.AddWithValue("#Entered_By", GetUserName())
insertcommand.Parameters.AddWithValue("#Time_Entered", Now)
insertcommand.ExecuteNonQuery()
End If
keypos = keypos + 1
Next
Connexion.Close()

Identical datatable 2 columns merging and summing one column in vb.net

I have 5 datatables which having each 3 columns (ID, Brand, Quanitiy) to derive the opening, purchase, sales and closing stock. The First 3 datatables should be merged and sum up to derive the opening stock as on given period. 4 th datatable is for Purchases done for the given period. The last one Datatable is for Sales done for the given period.
Here is my question:
How can i merge the 3 datatables and using the first 2 columns and summing the values?
How can i use the tables in crystal reports?
My code is :
Dim con As New ClassConnection
If con.Conn.State = ConnectionState.Closed Then con.Conn.Open()
'To get Opening Stock in Full Quantity
Dim sql As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum (tblOp_Details.Net_Qty) AS Quantity FROM tblOp_Stock INNER JOIN (tblBrand INNER JOIN" & _
" tblOp_Details ON tblBrand.B_ID = tblOp_Details.B_ID) ON tblOp_Stock.Stk_ID = tblOp_Details.Stk_ID" & _
" WHERE tblOp_Stock.God_ID = #GID GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'To get Purchases < start date and adding to the opening stock
Dim sql1 As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum (tblPur_Details.Net_Qty) AS Quantity FROM tblPurchase INNER JOIN (tblBrand INNER JOIN" & _
" tblPur_Details ON tblBrand.B_ID = tblPur_Details.B_ID) ON tblPurchase.Pur_ID = tblPur_Details.Pur_ID" & _
" WHERE tblPurchase.God_ID = #GID AND tblPurchase.Rec_Date < #SDate GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'To get Sales < Start date and subtracting to the above
Dim sql2 As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum (tblSales_Details.Net_Qty) AS Quantity FROM tblSales INNER JOIN (tblBrand INNER JOIN" & _
" tblSales_Details ON tblBrand.B_ID = tblSales_Details.B_ID) ON tblSales.Sale_ID = tblSales_Details.Sale_ID" & _
" WHERE tblSales.God_ID = #GID AND tblSales.Sale_Date < #SDate GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'The above 3 condition is for deriving opening stock as on given date
'To get Purchases >= Start Date and <= Start Date
Dim sql3 As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum(tblPur_Details.Net_Qty) AS Quantity FROM tblBrand INNER JOIN (tblPurchase INNER JOIN" & _
" tblPur_Details ON tblPurchase.Pur_ID = tblPur_Details.Pur_ID) ON tblBrand.B_ID = tblPur_Details.B_ID" & _
" WHERE tblPurchase.God_ID = #GID And tblPurchase.Rec_Date >= #SDate And tblPurchase.Rec_Date" & _
" <= #EDate GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'The above condition is for deriving Purchases as on given date
'To get Sales >= Start Date and <= Start Date
Dim sql4 As String = "SELECT tblBrand.B_ID AS ID, tblBrand.B_Name AS Brand," & _
" Sum(tblSales_Details.Net_Qty) AS Quantity FROM tblBrand INNER JOIN (tblSales INNER JOIN" & _
" tblSales_Details ON tblSales.Sale_ID = tblSales_Details.Sale_ID) ON tblBrand.B_ID = tblSales_Details.B_ID" & _
" WHERE tblSales.God_ID = #GID And tblSales.Sale_Date >= #SDate And tblSales.Sale_Date <= #EDate" & _
" And tblSales_Details.S_Active = #SAct GROUP BY tblBrand.B_ID, tblBrand.B_Name"
'The above condition is for deriving Sales as on given date
Dim da As New OleDb.OleDbDataAdapter(sql, con.Conn)
Dim da1 As New OleDb.OleDbDataAdapter(sql1, con.Conn)
Dim da2 As New OleDb.OleDbDataAdapter(sql2, con.Conn)
Dim da3 As New OleDb.OleDbDataAdapter(sql3, con.Conn)
Dim da4 As New OleDb.OleDbDataAdapter(sql4, con.Conn)
da.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da1.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da1.SelectCommand.Parameters.AddWithValue("#SDate", Me.dtpStart.ToString)
da2.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da2.SelectCommand.Parameters.AddWithValue("#SDate", Me.dtpStart.ToString)
da3.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da3.SelectCommand.Parameters.AddWithValue("#SDate", Me.dtpStart.ToString)
da3.SelectCommand.Parameters.AddWithValue("#EDate", Me.dtpEnd.ToString)
da4.SelectCommand.Parameters.AddWithValue("#GID", Me.stBar_G_ID.Text)
da4.SelectCommand.Parameters.AddWithValue("#SDate", Me.dtpStart.ToString)
da4.SelectCommand.Parameters.AddWithValue("#EDate", Me.dtpEnd.ToString)
da4.SelectCommand.Parameters.AddWithValue("#SAct", "Yes")
Dim dt As New DataTable
Dim dt1 As New DataTable
Dim dt2 As New DataTable
Dim dt3 As New DataTable
Dim dt4 As New DataTable
Ignoring the fact that such operations should be done in the database instead of memory, you can use Linq-To-DataSet which is a subset of Linq-To-Objects.
If you want to concatenate the three tables, group by ID + Brand to get the sum of Quantity:
Dim allRows = dt1.AsEnumerable().Concat(dt2.AsEnumerable()).Concat(dt3.AsEnumerable())
Dim query = From row In allRows
Let GroupColumns = New With {
.Id = row.Field(Of Int32)("Id"),
.Brand = row.Field(Of String)("Brand")
}
Group row By GroupColumns Into Group
Select New With {
.Id = GroupColumns.Id,
.Brand = GroupColumns.Brand,
.SumQuantity = Group.Sum(Function(row) row.Field(Of Int32)("Quantity"))
}
Fill the merged table from the query:
Dim dt As DataTable = dt1.Clone() ' empty, same columns
For Each x In query
Dim row = dt.Rows.Add()
row.SetField("Id", x.Id)
row.SetField("Brand", x.Brand)
row.SetField("Quantity", x.SumQuantity)
Next

adding results of query against datatable to a column in another datatable in visual basic

Problem: I have populated a datatable using a query on a sql server database. The query is:
Select ID, startDate, codeID, Param,
(select top 1 startDate from myTable
where ID='" & ID & "' and Param = mt.param and codeID = 82 and startDate >= '" & startDate & "' and startDate >=mt.startDate
ORDER BY startDate)endTime,
from myTable mt where ID = '" & ID & "'
AND (startDate between '" & startDate & "' AND '" & endDate & "' AND (codeID = 81))
I want a new column called duration that will be the difference between endTime and startDate in milliseconds. I can't just add another subquery to the above query since the endTime column didn't exist until the subquery was ran.
So, is there a way to maybe run the first query to populate the datatable, then run a query like:
Select DateDiff(ms,endTime,startDate)
On its own and add its results to a new column in my datatable?
You can always nest that in another query:
select *, datediff(ms, startDate, endTime)
from (
<your existing query here>
) t
And while I'm here, it seems you need a lesson in parameterized queries:
Dim result As New DataTable
Dim Sql As String = _
"SELECT *, datediff(ms, startDate, endTime) FROM (" & _
"SELECT ID, startDate, codeID, Param, " & _
"(select top 1 startDate from myTable " & _
"where ID= #ID and Param = mt.param and codeID = 82 and startDate >= #startDate and startDate >=mt.startDate " & _
"ORDER BY startDate) endTime " & _
" FROM myTable mt " & _
" WHERE ID = #ID AND startDate between #startDate AND #endDate AND codeID = 81" & _
") t"
Using cn As New SqlConnection("connection string"), _
cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("#ID", SqlDbType.VarChar, 10).Value = ID
cmd.Parameters.Add("#startDate", SqlDbType.DateTime).Value = Convert.ToDateTime(startDate)
cmd.Parameters.Add("#endDate", SqlDbType.DateTime).Value = Convert.ToDateTime(endDate)
cn.Open()
Using rdr = cmd.ExecuteReader()
result.Load(rdr)
rdr.Close()
End Using
End Using