I am trying to filter a table from Ms access DB in visual studio by ID (PID) column but I can't figure out how to convert int to string, or to make it work.
Any ideas please.
con.ConnectionString = dbProvider & dbSource
con.Open()
If PIDfindTextBox.Text = "" Then
MessageBox.Show("Please enter a Patient ID number")
Else
PatienrocordBindingSource.Filter = "((PID,'system.string') like '" & PIDfindTextBox.Text & "')"
If PatienrocordBindingSource.Count <> 0 Then
With dataGridView1.DataSource = PatienrocordBindingSource
End With
Else
MessageBox.Show("Searched Patient ID was not found")
PatienrocordBindingSource.Filter = Nothing
End If
End If
End Sub
Your code is very confused. It opens a database connection then sets a bindingsource filter, this isn't really how things go
A bindingsource is a device that sits between a model of data such as a datatable (which is not a table in a database) and a UI element such as a datagridview or other controls. The bindingsource can filter the data it finds in the model. None of this is anything to do with filling the model up with data in the first place, which often is done by pulling it out of a database
You can probably avoid interacting with a database connection entirely; if you use an OledbDataAdapter you can pull data out of your database and load it into a datatable in your program's memory
You thus have a choice of where to filter your data. You either load the entire database into your program's memory and then use bindingsource filter to show just the one if you want - all the data lives in the datatable and only some of it passes through the bindingsource ..
Or you only download some of the data out of the database and into the datatable, and then you don't need to filter it in the bindingsource
You can also take a hybrid approach of loading, say, 10 records into the datatable and then filtering In the bindingsource
Choose your scenario - most people opt for the middle one where you just download the data you need. There are plenty of examples out there but as a rough template, searching a database table by I'd and pulling the results would look like:
Dim da as New OleDbDataAdapter("SELECT * FROM Person WHERE Id =?", "connection string here")
da.SelectCommand.Parameters.AddWithValue("id", Convert.ToInt32(idTextbox.Text))
Dim dt as New DataTable
da.Fill(dt)
bindingsource.DataSource = dt
If you had 10 rows in your datatable and wanted to filter to just some one id
bindingsource.Filter = "[Id] = " & idFilterTextBox.Text
You don't need to use both of these approaches; use the one that is right for your context
Related
I have read every single SO question and online article regarding this, and I get confused in a couple different instances.
As my project sits, I have tried to create a Report (Report2.rdlc) manually and drag different fields from DataSources onto the report, and use that report as the data source for the ReportViewer. This did not work. I need to use the DataTable I created from a SqlDataAdapterbecause it decrypts specific rows. I tried creating a DataSet and filling it with the DataTable, however I was unable to perform that, also.
I don't understand: if I have a ReportViewer control on a
WinForm, what all I need in my code to bind a data source to it.
Is the code even creating a report and utilizing the report for
the ReportViewer?
The DataTable name is dt and the ReportViewer control is rv1.
Here's the code I have been toying around with, however I am not sure what to put as the Report Path
Dim RDS1 As ReportDataSource = New ReportDataSource("Test Report", dt)
rv1.LocalReport.DataSources.Clear()
rv1.ProcessingMode = ProcessingMode.Local
rv1.LocalReport.EnableExternalImages = True
rv1.LocalReport.ReportEmbeddedResource = "Your Report Path"
rv1.LocalReport.DataSources.Add(RDS1)`.
The worst part is, the ReportViewer just shows up blank. There are no errors or any indicators as to what could be going wrong.
The information within the DataTable dt is all correct (verified by viewing it in a DGV). I am just trying to use that data in a Report / ReportViewer.
Does anyone have any advice? I cannot seem to catch a break on this issue.
Note: Exporting to Excel is not an option. There are encrypted values that require decryption. The report needs to be printable.
Edit: Here is how I populate the DataTable:
Dim cmd As New SqlCommand
cmd.CommandText = "Select * FROM Participant " & _
"WHERE FIRST_NM_TXT = #searchFirst " & _
"OR LAST_NM_TXT = #searchLast"
cmd.Parameters.AddWithValue("#searchFirst", SearchFirstTxt.Text)
cmd.Parameters.AddWithValue("#searchLast", SearchLastTxt.Text)
Dim adapter As New SqlDataAdapter(cmd)
adapter.Fill(dt)
So, here we have the DataTable with the correct data in it. I have then gone to the Project Name, Added a new Report (Report1.rdlc), and from here I am unsure of the next steps. If I create a DataSet dynamically, should I see it in this window?
Since this seems to be a popular thread, I'll explain how I was able to do this in quick/easy steps.
Right click on your porject -> Add New Item -> Selection Report.rdlc
Top left (Data Source) -> New -> Dataset (select Database [Next ->] Dataset [Next ->] Your DB connection.
"Choose your database objects" screen -> Select Tables
"Choose the dataset" screen -> This will be reset at run time. Make sure you remember the name of this Dataset, because it will be used in the code.
Add ReportViewer control (under Reporting) to the form. Select reportviewer control and go to properties (bottom right pane in VS). Select Local Report's property and set ReportEmbeddedResource to point to the report path we just created. ** ProjectName.ReportName.rdlc**
Peform the usual:
Public DataSet FillDS()
//Try Catch block & other code omitted
Dim cmd As New SqlCommand
cmd.CommandText = "Select * FROM Participant " & _
"WHERE FIRST_NM_TXT = #searchFirst " & _
"OR LAST_NM_TXT = #searchLast"
cmd.Parameters.AddWithValue("#searchFirst", SearchFirstTxt.Text)
cmd.Parameters.AddWithValue("#searchLast", SearchLastTxt.Text)
Dim adapter As New SqlDataAdapter(cmd)
adapter.Fill(dt)
Then, we bind the datasource at run time.
DataSet yourDS = FillDS();
ReportDataSource rds = New ReportDataSource("YourDataSetNameFromStep4", yourDS.Tables[0]);
yourReportViewerName.localreport.datasources.clear();
yourReportViewerName.localreport.datasources.add(rds);
yourReportViewerName.refreshreport();
If there is something I could post in here to help anyone else, let me know.
Some things to check:
"Test Report" must be the name used in the report designer. It's case sensitive.
The dt must match the name used in the report designer too
"Your report Path" should be of the form "namespace.reportname.rdlc" . It's case sensitive.
EDIT:
The approach I normally use utilises an extra layer, in the form of a BindingSource as follows:
Fill a strongly-typed dataset using the ad-hoc query and a SqlDataAdapter.
Dim a Bindingsource and set its DataSource to the dataset and its DataMember to the table name.
Dim a ReportDataSource and set its name to the name used in the report designer, and its value to the BindingSource
eg
Using cn As New SqlConnection(gcs)
cn.Open()
Dim sa As New SqlDataAdapter(sql, cn)
sa.SelectCommand.CommandTimeout = cGlobals.ReportTimeout
sa.Fill(ds, "Foos")
End Using
bs.DataSource = ds
bs.DataMember = "Foos"
Dim rds As New ReportDataSource
rds.Name = "dsFooList_Foos"
rds.Value = bs
rv1.LocalReport.DataSources.Add(rds)
Me.Show()
rv1.RefreshReport()
Edit 2: At the point in your screenshot, drop down the datasources and pick the one you want. It will then appear in the Report Data window, which may be hiding in the 'View' menu (it's only there when you're working with a report) Then you can add a Table to the report from the toolbox, and then drag the fields from the Report Data window to the table cells.
something similar I have made for my "report loader", please check this link, it is written in C# but it will give you an idea how to do it.
How to bind dynamically datasource to reportviewer on windows forms c#
adding updating everything is fine even delete command is working but the strange part is after executing del command from vb.net application it swipes the position of EMPLOYEE_IDAND NAMEit shows normally in datagridviewafter adding or updating but specifically after deleting the record position of these to column changes until I stop the application and re run the entire project for debugging
Dim con As New MySqlConnection("server=localhost; user=root; password=Masoom1; database=airtech_db; convert zero datetime=true;")
Dim cmd As New MySqlCommand
Dim dt As New DataTable
Dim da As New MySqlDataAdapter
Dim sql As String
Dim DR As MySqlDataReader
Dim SQL_CMD_TXT As String
SQL_CMD_TXT = "DELETE FROM `employees` WHERE (`EMPLOYEE_ID` ='" &
EMPLOYEE_DEL_FRM.DEL_ID_TXT.Text & "'); SELECT * FROM `employees`;"
EMPLOYEE_DEL_FRM.Controls.Add(OBJECT_DATAGRIDVIEW)
With OBJECT_DATAGRIDVIEW
.Size = New Size(587, 242)
.Location = New Size(221, 171)
End With
Try
'DB CMD EXECUTION
con.Open()
With cmd
sql = SQL_CMD_TXT
.Connection = con
.CommandText = sql
End With
da.SelectCommand = cmd
da.Fill(dt)
'Command for datagridview object
With OBJECT_DATAGRIDVIEW
.DataSource = dt
'Scroll to the last row.
.Name = "MYDATAGRIDVIEW"
.FirstDisplayedScrollingRowIndex = .RowCount - 1
End With
con.Close()
Catch ex As Exception
Dim MEB = MessageBox.Show("ERROR FOR SQL CMD EXECUTION SECTION-" & ex.Message,
"SQL CMD EXECUTION", MessageBoxButtons.OK, MessageBoxIcon.Error)
Exit Sub
End Try
attaching the normal and after delete result in images
enter image description here
I am not sure I completely understood your problem, but your problem could that the datagridview generates the columns automatically. See: DataGridView.AutoGenerateColumns
Instead of doing SELECT * FROM is would better to select just the fields you need. If you add more fields to your table in the future, the columns in the datagridview may be displaced because they are in no particular order.
Rather than add the datagridview to your form at runtime:
EMPLOYEE_DEL_FRM.Controls.Add(OBJECT_DATAGRIDVIEW)
I would add it directly in the form layout (so you can see it at design time), and then customize it, bind each column to a database field. The appearance of the grid will be more predictable. Here is a small guide: How to bind datatable/list to datagridview with headers?
Relying on AutoGenerateColumns is not a great idea, because this will show all columns (usually not desirable) and not necessarily in the order that you want.
Other remarks:
Records can be edited or deleted directly in the datagridview, by simply selecting one or more rows, and pressing the Del key. Then just invoke the DataAdapter to commit the changes to the database. You should not even be doing DELETE FROM. Just let the user use the datagridview. The benefit is that if the user makes a mistake, you can roll back changes because you are using a datatable. Here you are deleting immediately and without warning.
Don't do stuff like:
SQL_CMD_TXT = "DELETE FROM `employees` WHERE (`EMPLOYEE_ID` ='" &
EMPLOYEE_DEL_FRM.DEL_ID_TXT.Text & "'); SELECT * FROM `employees`;"
Use parameterized queries instead, this code is insecure and will choke on single quotes or special characters (try it !). Here is a simple example: FAQ: How do I make a parameterized query in the database with VB.NET?. Please use parameterized queries from now on, don't develop bad habits that will always bite you sooner or later. The security risk alone is too high.
Also I am wondering why you did stacked queries. It would better to separate the SELECT from the DELETE.
In this code variable sql is not needed:
With cmd
sql = SQL_CMD_TXT
.Connection = con
.CommandText = sql
End With
Just use SQL_CMD_TXT directly. Otherwise it makes the code more difficult to follow.
I'm making a WinForms application using VB.NET. I have a DataGridView that I am using to display results of a query to an SQL-Server Database. This works fine:
Dim SQL As New SqlConnection()
Dim CMD As New SqlCommand()
Dim ADP As New SqlDataAdapter()
Dim TBL As New DataTable()
SQL.Close()
SQL.ConnectionString = "Server=" & GetServerIP() & ";Database=" & GetDB() & ";User Id=" & userID & ";Password=" & pass & ";"
CMD.Connection = SQL
CMD.CommandText = "SELECT * FROM " & table
SQL.Open()
ADP.SelectCommand = CMD
TBL.Clear()
ADP.Fill(TBL)
DataGridView1.DataSource = TBL
The issue is that the DataGridView has a column NAME which is empty in every row.
I tried changing the query to SELECT SEQ_NUM FROM CONFIG_SYS that resulted in a DataGridView with a NAME and SEQ_NUM column. I tried calling DataGridView1.Columns.Clear() before the DataGridView1.DataSource = TBL and that does not have an effect on anything. I should mention that if I query any table in my database that does not have a NAME column, I get the same results with an empty NAME column in my DataGridView.
My theory is that a DataGridView automatically adds NAME as the first column, expecting the Database Table to be set up with a NAME column as the primary key. However, my table does not have NAME, it has a column called SEQ_NUM as the primary key. I am able to work around this by doing DataGridView1.Columns("NAME").Visible = False but I don't feel that this is the best way to do it.
Is there a better way to handle this - I'd like the column to not exist at all in the data grid, not just not be visible.
What was causing my issue was the fact that I was calling TBL.Clear() incorrectly.
Calling DataTable.Clear() will clear the Data from a DataTable but it will leave the columns in place.
Instead I should have been calling TBL.Columns.Clear(), which gets rid of the columns of the DataTable. However, using Breakpoints and Visual Studio's DataTable Visualizer I noticed that only calling TBL.Columns.Clear() left the empty rows still in the DataTable. Therefore, to answer the question of how to get rid of a column in a DataGridView that you don't know why/how is there, I suggest to call:
DataTable.Clear()
DataTable.Columns.Clear()
Before setting your DataGridView equal to your DataTable.
Taken from the MSDN:
The .Clear() Method of a DataTable Class "clears the DataTable of all data."
The DataTable.Columns Property gets "a DataColumnCollection that contains the collection of DataColumn objects for the table"
The DataColumnCollection Class also has a .Clear() Method which "clears the collection of any columns."
Thank you #TnTinMn for pointing me in the right direction by using breakpoints and #LarsTech for making me realize that I harshly mixed up DataGridView and DataTable in my original answer.
I hope this post can help others prevent themselves from ripping their hair out about where a non-existent column in their databases seemingly materialized from... If this does not fix your specific issue. I would also check the Query, Database Table setup, and the DataGridView; but for me the issue was with the DataTable.
I'm looking for a pseudo code to write a VB.NET cursor to select columns from one table in one database and inserting it into another table in a different database (they are *not on the same server) using data adapter etc.
I just need something to refer to as I learn. Thanks
Dim selectStr As String = _
"select * from db1"
Dim insertStr As String = _
"insert into db2(col1)"
Try
da_adapter = New OleDb.OleDbDataAdapter(selectStr, connStr)
da2_adapter = New OleDb.OleDbDataAdapter(insertStr, connStr2)
da_adapter.SelectCommand.CommandTimeout = 720
da_adapter.Fill(ds)
da2_adapter.SelectCommand.CommandTimeout = 720
da2_adapter.Fill(ds)
Catch ex As Exception
End Try
In your original code, this part is wrong:
da2_adapter = New OleDb.OleDbDataAdapter(insertStr, connStr2)
When you create a data adapter that way, the SQL statement you provide becomes part of the SelectCommand. You want yours to be part of the InsertCommand, which you need to do yourself:
Dim cmd2 As New OleDb.OleDbCommand(insertStr, connStr2)
da2_adapter = New OleDb.OleDbDataAdapter
da2_adapter.InsertCommand = cmd2
Also, you need to set the AcceptChangesDuringFill property of the first data adapter to False. That way, instead of setting the RowState of all the rows to Unchanged after populating the DataTable, they will remain as Added and ready to be inserted.
You then need to call Update on the second data adapter to save the data rather than calling Fill, which retrieves data.
I have read every single SO question and online article regarding this, and I get confused in a couple different instances.
As my project sits, I have tried to create a Report (Report2.rdlc) manually and drag different fields from DataSources onto the report, and use that report as the data source for the ReportViewer. This did not work. I need to use the DataTable I created from a SqlDataAdapterbecause it decrypts specific rows. I tried creating a DataSet and filling it with the DataTable, however I was unable to perform that, also.
I don't understand: if I have a ReportViewer control on a
WinForm, what all I need in my code to bind a data source to it.
Is the code even creating a report and utilizing the report for
the ReportViewer?
The DataTable name is dt and the ReportViewer control is rv1.
Here's the code I have been toying around with, however I am not sure what to put as the Report Path
Dim RDS1 As ReportDataSource = New ReportDataSource("Test Report", dt)
rv1.LocalReport.DataSources.Clear()
rv1.ProcessingMode = ProcessingMode.Local
rv1.LocalReport.EnableExternalImages = True
rv1.LocalReport.ReportEmbeddedResource = "Your Report Path"
rv1.LocalReport.DataSources.Add(RDS1)`.
The worst part is, the ReportViewer just shows up blank. There are no errors or any indicators as to what could be going wrong.
The information within the DataTable dt is all correct (verified by viewing it in a DGV). I am just trying to use that data in a Report / ReportViewer.
Does anyone have any advice? I cannot seem to catch a break on this issue.
Note: Exporting to Excel is not an option. There are encrypted values that require decryption. The report needs to be printable.
Edit: Here is how I populate the DataTable:
Dim cmd As New SqlCommand
cmd.CommandText = "Select * FROM Participant " & _
"WHERE FIRST_NM_TXT = #searchFirst " & _
"OR LAST_NM_TXT = #searchLast"
cmd.Parameters.AddWithValue("#searchFirst", SearchFirstTxt.Text)
cmd.Parameters.AddWithValue("#searchLast", SearchLastTxt.Text)
Dim adapter As New SqlDataAdapter(cmd)
adapter.Fill(dt)
So, here we have the DataTable with the correct data in it. I have then gone to the Project Name, Added a new Report (Report1.rdlc), and from here I am unsure of the next steps. If I create a DataSet dynamically, should I see it in this window?
Since this seems to be a popular thread, I'll explain how I was able to do this in quick/easy steps.
Right click on your porject -> Add New Item -> Selection Report.rdlc
Top left (Data Source) -> New -> Dataset (select Database [Next ->] Dataset [Next ->] Your DB connection.
"Choose your database objects" screen -> Select Tables
"Choose the dataset" screen -> This will be reset at run time. Make sure you remember the name of this Dataset, because it will be used in the code.
Add ReportViewer control (under Reporting) to the form. Select reportviewer control and go to properties (bottom right pane in VS). Select Local Report's property and set ReportEmbeddedResource to point to the report path we just created. ** ProjectName.ReportName.rdlc**
Peform the usual:
Public DataSet FillDS()
//Try Catch block & other code omitted
Dim cmd As New SqlCommand
cmd.CommandText = "Select * FROM Participant " & _
"WHERE FIRST_NM_TXT = #searchFirst " & _
"OR LAST_NM_TXT = #searchLast"
cmd.Parameters.AddWithValue("#searchFirst", SearchFirstTxt.Text)
cmd.Parameters.AddWithValue("#searchLast", SearchLastTxt.Text)
Dim adapter As New SqlDataAdapter(cmd)
adapter.Fill(dt)
Then, we bind the datasource at run time.
DataSet yourDS = FillDS();
ReportDataSource rds = New ReportDataSource("YourDataSetNameFromStep4", yourDS.Tables[0]);
yourReportViewerName.localreport.datasources.clear();
yourReportViewerName.localreport.datasources.add(rds);
yourReportViewerName.refreshreport();
If there is something I could post in here to help anyone else, let me know.
Some things to check:
"Test Report" must be the name used in the report designer. It's case sensitive.
The dt must match the name used in the report designer too
"Your report Path" should be of the form "namespace.reportname.rdlc" . It's case sensitive.
EDIT:
The approach I normally use utilises an extra layer, in the form of a BindingSource as follows:
Fill a strongly-typed dataset using the ad-hoc query and a SqlDataAdapter.
Dim a Bindingsource and set its DataSource to the dataset and its DataMember to the table name.
Dim a ReportDataSource and set its name to the name used in the report designer, and its value to the BindingSource
eg
Using cn As New SqlConnection(gcs)
cn.Open()
Dim sa As New SqlDataAdapter(sql, cn)
sa.SelectCommand.CommandTimeout = cGlobals.ReportTimeout
sa.Fill(ds, "Foos")
End Using
bs.DataSource = ds
bs.DataMember = "Foos"
Dim rds As New ReportDataSource
rds.Name = "dsFooList_Foos"
rds.Value = bs
rv1.LocalReport.DataSources.Add(rds)
Me.Show()
rv1.RefreshReport()
Edit 2: At the point in your screenshot, drop down the datasources and pick the one you want. It will then appear in the Report Data window, which may be hiding in the 'View' menu (it's only there when you're working with a report) Then you can add a Table to the report from the toolbox, and then drag the fields from the Report Data window to the table cells.
something similar I have made for my "report loader", please check this link, it is written in C# but it will give you an idea how to do it.
How to bind dynamically datasource to reportviewer on windows forms c#