How to Print DatagridView? - vb.net

I am using simple data grid view for displaying all records using select statement in stored Procedure...the displayed list view is okay i want to print it out as it is. What should i do
like we print the excel sheets...
Thanks For The Solution In Advance..
My Logic For Filling Data Grid View Is :
Public Sub FillDataGrid(ByVal myGrid As DataGridView, ByVal Sqlstring As String)
myGrid.Enabled = False
Dim myDbf As New SqlDataAdapter(Sqlstring, myConnection)
Dim myDataset As New DataSet
myDataset.Clear()
myDbf.Fill(myDataset, "Finddata")
myDataset.Tables("Finddata").DefaultView.AllowNew = False
myGrid.DataSource = myDataset.Tables("FindData")
myGrid.AutoResizeColumns()
myGrid.Enabled = True
End Sub
Above function will be called on level from module by passing datagrid & stored procedure in parameters.

Related

Why isn't my datagridview being populated after setting the datasource?

I'm working on a vb.net Windows forms application. I've got a datagridview that I'm trying to populate by a datatable and cannot get it to show the data. I've tried assigning the datatable directly to datagridview and using a binding source. I've checked the column names and tried to refresh the grid after setting the datasource. If I go back into the code, I can see that the datasource has data, but data will not appear in the grid. What am I doing wrong?
Here's the database table creation:
Dim dsReturns As New DataSet("Returns Dataset")
Dim dtReturns = dsReturns.Tables.Add("Returns Datatable")
dtReturns.Columns.Add("Quantity")
dtReturns.Columns.Add("ItemName")
Dim drReturns As DataRow = dtReturns.NewRow
drReturns("Quantity") = qtyh(key).ToString
drReturns("ItemName") = ItemFunctions.GetItemName(item_id)
dsReturns.Tables("Returns Datatable").Rows.Add(drReturns)
This produces a datatable that looks like this:
Here's the code assigning the datatable to the datagridview. I've tried it both with and without using the binding source.
dgvReturns = new DataGridView()
Dim bsReturns As New BindingSource()
bsReturns.DataSource = dsReturns.Tables("Returns Datatable")
dgvReturns.DataSource = bsReturns
Here's the code from the Designer that creates the datagridview. I didn't write the code, it's all auto generated. I created a new datagridview in Design mode and then added two columns.
Friend WithEvents dgvReturns As DataGridView
Friend WithEvents Quantity As DataGridViewTextBoxColumn
Friend WithEvents ItemName As DataGridViewTextBoxColumn
Me.dgvReturns = New System.Windows.Forms.DataGridView()
Me.Quantity = New System.Windows.Forms.DataGridViewTextBoxColumn()
Me.ItemName = New System.Windows.Forms.DataGridViewTextBoxColumn()
CType(Me.dgvReturns,System.ComponentModel.ISupportInitialize).BeginInit
Me.dgvReturns.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize
Me.dgvReturns.Columns.AddRange(New System.Windows.Forms.DataGridViewColumn() {Me.Quantity, Me.ItemName})
Me.Quantity.DataPropertyName = "Quantity"
Me.Quantity.HeaderText = "Quantity Returned"
Me.Quantity.Name = "Quantity"
Me.ItemName.HeaderText = "Item Name"
Me.ItemName.Name = "ItemName"
Me.dgvReturns.Location = New System.Drawing.Point(13, 13)
Me.dgvReturns.Name = "dgvReturns"
Me.dgvReturns.Size = New System.Drawing.Size(465, 150)
Me.dgvReturns.TabIndex = 1
Me.Controls.Add(Me.dgvReturns)
CType(Me.dgvReturns,System.ComponentModel.ISupportInitialize).EndInit
Here's a screenshot of the table in the Designer:
All I end up with is a blank grid:
Update #1 - Showing all code for the form
Here's the full code for the form showing the constructor.
Public Class frmReturnsDialog
Public Sub New(dsReturns As DataSet)
InitializeComponent()
dgvReturns = new DataGridView()
Dim bsReturns As New BindingSource()
bsReturns.DataSource = dsReturns.Tables("Returns Datatable")
dgvReturns.DataSource = bsReturns
End Sub
End Class

Datatables Not Merging VB.NET

I have some code that is intended to:
1. Loop through a datagrid that is user populated
2. Search an access database using the input criteria
3. Return the results as a datatable
4. Merge additional results to that datatable
5. Bind the merged table results to a DataGridView
The query works, results return as expected with a single value search. The query will also return one of the two test values if I use the user input DataGridView. However, it will not combine the two results before outputting to the results_DataGridView. I have also tried using .Fill from the adapter to add onto my temp table and use that as the datasource.
Option Strict On
Dim dt_TempTable As New DataTable
Dim dt_ContentsTable As New DataTable
Dim SerialNumbers As New List(Of String)
Dim PanelIDs As New List(Of String)
Dim MultiSearch As Boolean
Private Sub bgwk_data_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgwk_data.DoWork
If Not (MultiSearch) Then
Retrieveinfo(Me.txt_SerialNumber.Text, Me.txt_PanelID.Text) 'Local
Else
Dim arrSN As String() = SerialNumbers.ToArray()
Dim arrPID As String() = PanelIDs.ToArray()
For i = 0 To arrSN.Count - 1
If i > 0 Then
Retrieveinfo(arrSN(i), arrPID(i)) 'Local - Run query and create a new temp table of results
dt_ContentsTable.Merge(dt_TempTable) 'Merge new temp table to current contents table
Else
dt_ContentsTable = Retrieveinfo(arrSN(i), arrPID(i)) 'Return the original temp table to the contents table (datagridview datasource)
End If
Next
End If
End Sub
'Gets the Data by SerialNumber and saves it to dt_TempTable to be bound afterwards
Private Function Retrieveinfo(SerialNumber As String, PanelID As String) As DataTable
Dim ds As New datasource
Dim tblAdapt As New datasourceTableAdapters.toHTML_SPC_DataTableAdapter
tblAdapt.GetData(dt_TempTable, SerialNumber, PanelID)
Return dt_TempTable 'Return the table
End Function
'Updates dg_data with the datatable from Retrieveinfo and refreshes the form
Private Sub bgwk_dataRunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgwk_data.RunWorkerCompleted
'Unlocks ability to search new things
Me.txt_PanelID.ReadOnly = False
Me.txt_SerialNumber.ReadOnly = False
Me.dg_data.ReadOnly = False
'Binds the backgroundworker results to the datagridview
Me.dg_data.DataSource = Nothing
Me.dg_data.DataSource = dt_ContentsTable
Me.dg_data.Refresh()
Me.Refresh()
End Sub
I understand that merge can be used on DataTables, but perhaps this is incorrect usage?
I'd go with a condition in the multi-search loop:
If dt_ContentsTable.Rows.Count = 0 Then
dt_ContentsTable = dt_TempTable.Clone()
End If
dt_ContentsTable.Merge(dt_TempTable)
This way, the first time, its at least creating the columns of the dt_ContentsTable.
I also don't see any code in the single search where dt_ContentsTable is assigned. So, in the single search, I recommend you assign dt_ContentsTable to dt_TempTable.

Adding Data to DataTable

This code is recording the inserted IDs in arraylist and when press on button it should create loop for this array and get the data of each ID from the array and put it in Datatable and add the new data while looping to the datatable and finaly show it in datagridview .
The problem in the result when I insert one record it works fine but when I insert more than one the datagridview shows just the last one , what the mistake that I Done ?!!
In Mainform
Public Inserted_record_hold_dt As New DataTable
Public Inserted_record_dt As New DataTable
Public Sub Addcolumnstodatagrid()
Inserted_record_dt.Columns.Add("ID")
Inserted_record_dt.Columns(0).AutoIncrement = True
Inserted_record_dt.Columns.Add("drawingname")
Inserted_record_dt.Columns.Add("serial")
End Sub
and call this in main_Load
Addcolumnstodatagrid()
And this in the show button when click to loop on the array list that already have the latest ID's that has been added
Private Sub show_btn_Click(sender As System.Object, e As System.EventArgs) Handles show_btn.Click
Dim InsertedID As Integer
Inserted_record_dt.Clear()
Dim R As DataRow = Inserted_record_dt.NewRow
'Loop For each ID in the array "Inserted_List_Array"
For Each InsertedID In mainadd.Inserted_List_Array
'MsgBox(InsertedID.ToString)
Dim cmd As New SqlCommand("select drawingname , serial from main where drawingid = '" & InsertedID & "'", DBConnection)
DBConnection.Open()
Inserted_record_hold_dt.Load(cmd.ExecuteReader)
Try
R("drawingname") = Inserted_record_hold_dt.Rows(0).Item(0)
R("serial") = Inserted_record_hold_dt.Rows(0).Item(1)
Inserted_record_dt.Rows.Add(R)
Catch
End Try
'MsgBox("added")
DBConnection.Close()
cmd = Nothing
Inserted_record_hold_dt.Clear()
Next
sendmail.Show()
sendmail.Mail_DGView.DataSource = Inserted_record_dt
End Sub
Please tell me what is the problem in my code .
Your mistake is in declaring the R variable just one time outside the loop. In this way you continuously replace the values on the same instance of a DataRow and insert always the same instance.
Just move the declaration inside the loop
For Each InsertedID In mainadd.Inserted_List_Array
......
Try
Dim R As DataRow = Inserted_record_dt.NewRow
R("drawingname") = Inserted_record_hold_dt.Rows(0).Item(0)
R("serial") = Inserted_record_hold_dt.Rows(0).Item(1)
Inserted_record_dt.Rows.Add(R)
Catch
....
Next
Another important thing to do is to remove the empty Try/Catch because you are just killing the exception (no message, no log) and thus you will never know if there are errors in this import. At the end you will ship a product that could give incorrect results to your end user.

Display DataGridView values in text boxes based on matching values - vb.net

I have an SQL query that returns 2 columns of values:
country | number
NA | 1
IN | 2
CN | 3
DE | 4
And so on.
I am trying to do one of the following:
Assign these values to variables I can copy to an excel workbook
Or just use the DGV as a medium to copy values to text boxes.
For example, I have a form with country labels and textboxes next to them. I would want to click a button and have the data copied to the matching text box.
DGV number value where DGV row value = CN would be 3 and that value would be copied to the CN value text box.
If you are only using the DGV as a medium, but not actually displaying it, use a dictionary instead. Output the SQLDataReader using the SQLcommand(cmd) with the country code being the key and the number being the value. Then its as simple as:
Dim dc As Dictionary(Of String, String) = New Dictionary(Of String, String)
Dim cmd As SqlCommand = "your query string"
cmd.Connection.ConnectionString = "your con string"
Using sqlrdr As SqlDataReader = cmd.ExecuteReader()
While (sqlrdr.Read())
dc.Add(sqlrdr(0), sqlrdr(1))
End While
End Using
Then just output to the textbox:
txtNA.Text = dc.Item("NA")
If the countries are fixed as your question refers, then you could use something like this:
First, use the names of the countries to name the TextBoxes (txtNA, txtIN, txtCN,...)
Then you can put this code:
Try
For i = 0 To DataGridView1.RowCount - 1
Me.Controls("txt" & DataGridView1.Rows(i).Cells(0).Value.ToString).Text = _
DataGridView1.Rows(i).Cells(1).Value.ToString()
Next
Catch
End Try
The following will not work 'as is' if using classes via dragging tables from the data source window in the ide. We would need to cast objects not to a DataTable but to the class definition in a TableAdapter, DataSet and BindingSource.
Here is a method which reads from SQL-Server database table, places data into a DataTable, data table become the data source for a BindingSource which becomes the data source for the DataGridView. Using a BindingSource we now use the BindingSource to access row data rather than the DataGridView and it's always best to go to the data source rather than the user interface.
BindingSource.Current is a DataRowView, drill down to Row property then field language extension method to get strongly typed data for the current row if there is a current row as you will note I am using two forms of assertions, first, do we have a data source and is the data source populated then we see if there is indeed a current row.
From here we can set variable, properties or control text to the field values of the current row.
Note in form load I seek a specific country (totally optional) and then if found go to that row.
Least but not last, I like using xml literals when doing SQL in code so there is no string concatenation and we can format the statement nicely.
Public Class Form1
''' <summary>
''' Permits obtaining row data in DataGridView
''' </summary>
''' <remarks></remarks>
Dim bsCountries As New BindingSource
Public Property Country As String
Public Property CountryNumber As Integer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt As New DataTable
Using cn As New SqlClient.SqlConnection With
{
.ConnectionString = My.Settings.KarenDevConnectionString
}
Using cmd As New SqlClient.SqlCommand With {.Connection = cn}
' xml literal to make command text
cmd.CommandText =
<SQL>
SELECT [ID],[Country],[Number]
FROM [Countries]
</SQL>.Value
cn.Open()
dt.Load(cmd.ExecuteReader)
dt.Columns("ID").ColumnMapping = MappingType.Hidden
bsCountries.DataSource = dt
DataGridView1.DataSource = bsCountries
' let's try and move to a country
Dim index As Integer = bsCountries.Find("Country", "CN")
If index > -1 Then
bsCountries.Position = index
End If
End Using
End Using
End Sub
''' <summary>
''' Put field values into TextBoxes
''' </summary>
''' <remarks></remarks>
Private Sub DoWork()
If bsCountries.DataSource IsNot Nothing Then
If bsCountries.Current IsNot Nothing Then
Dim row As DataRow = CType(bsCountries.Current, DataRowView).Row
TextBox1.Text = row.Field(Of String)("Country")
TextBox2.Text = row.Field(Of Integer)("Number").ToString
' we can also do this
Me.Country = row.Field(Of String)("Country")
Me.CountryNumber = row.Field(Of Integer)("Number")
End If
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
DoWork()
End Sub
End Class

Viewing selected columns

I'm doing .NET 3.5 programming in VB for a class. I have a .mdb database with 3 related tables, and a table adapter with some queries on it that look like this:
SELECT PropertyID, Street, Unit, City, Zip, Type, Bedrooms, Bathrooms, Area, MonthlyRent
FROM tblProperties
Then in a form i have a DataGridView. What i want to do is take the data that is returned from the query and display it in the DGV. However, when i do this, it displays all 35 columns in the database, not the 10 i selected (The ten are the only ones that have data in them however... so it's basically a table with a bunch of blank columns).
My current, inelegant solution is to return the query to a DataTable, then iterate through the table's columns, deleting the one's i dont want. This is not robust, efficient, and does not like me delete the primary key column.
My TA suggested trying to use an untyped databinding... he said this should display only the data I pull, but neither of us has been able to figure this out yet.
Thank You!
UPDATE
I'm not sure what you mean by the .aspx/.aspx.vb pages, but this is the query code i have from the table adapter
SELECT tblRent.PaymentID, tblTenant.TenantName, tblProperties.Street, tblProperties.Unit, tblProperties.City, tblRent.AmountPaid, tblRent.PaymentDate,
tblTenant.Telephone
FROM ((tblProperties INNER JOIN
tblRent ON tblProperties.PropertyID = tblRent.PropertyID) INNER JOIN
tblTenant ON tblProperties.PropertyID = tblTenant.PropertyID)
and here is where i use it in code:
Public Sub getRent()
propView.DataSource = TblPropertiesTableAdapter.GetAllRentReceipts()
propView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
propView.ReadOnly = True
End Sub
propView is a DataGridView that does not have a DataSource selected at load
I'm assuming that you're using Windows forms and a DataGridView with AutoGenerateColumns turned on.
If you add you own columns only the ones that you select will appear:
propView.AutoGenerateColumns = false
For Each //of the columns that you want
dim column as DataGridViewColumn = New DataGridViewColumn()
column.DataPropertyName = "DB field name"
column.HeaderText = "column title"
propView.Columns.Add( column )
Next
If you build the pages using tags, you'll want the following code in the page...
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1">
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:MY_ConnectionString %>"
SelectCommand="SELECT tblRent.PaymentID, tblTenant.TenantName, tblProperties.Street, tblProperties.Unit, tblProperties.City, tblRent.AmountPaid, tblRent.PaymentDate, tblTenant.TelephoneFROM ((tblProperties INNER JOIN tblRent ON tblProperties.PropertyID = tblRent.PropertyID) INNER JOIN tblTenant ON tblProperties.PropertyID = tblTenant.PropertyID)"></asp:SqlDataSource>
If alternatively you want to use code for the data layer, you could use something along the lines of the following...
Public Class DataLayer
Public Function GetData(ByVal query As String, ByVal params As System.Data.Common.DbParameter()) As System.Data.DataTable
Dim dt As New System.Data.DataTable
Dim constr As String = System.Configuration.ConfigurationManager.ConnectionStrings("constr").ConnectionString()
Using cnObject As New System.Data.SqlClient.SqlConnection(constr)
Using cmd As New System.Data.SqlClient.SqlCommand(query, cnObject)
If Not params Is Nothing Then
For Each param In params
cmd.Parameters.Add(param)
Next
End If
Using da As New System.Data.SqlClient.SqlDataAdapter(cmd)
da.Fill(dt)
Return dt
End Using
End Using
End Using
End Function
End Class
If you are using OLEDB connection, this function can be changed as follows (meaning you only have to change one function to update every use of it in the application - nice)
Public Function GetDataOLE(ByVal query As String, ByVal params As System.Data.Common.DbParameter()) As System.Data.DataTable
Dim dt As New System.Data.DataTable
Dim constr As String = System.Configuration.ConfigurationManager.ConnectionStrings("constr").ConnectionString()
Using cnObject As New System.Data.OleDb.OleDbConnection(constr)
Using cmd As New System.Data.OleDb.OleDbCommand(query, cnObject)
If Not params Is Nothing Then
For Each param In params
cmd.Parameters.Add(param)
Next
End If
Using da As New System.Data.OleDb.OleDbDataAdapter(cmd)
da.Fill(dt)
Return dt
End Using
End Using
End Using
End Function
This function works is a generic data layer that will take in any SQL Command and output the data in a DataTable, which can simply be bound to a grid view or similar. You can check that the "query" is only selecting the columns you want but debugging the code and checking the SQL command to your database.
I would build it into a class so that any page could access it to load data into a data table.
Your code would become
Public Sub getRent()
Dim dataLayer As New DataLayer()
Dim sqlText As String = "<insert your query text here>"
propView.DataSource = dataLayer.getData(sqlText, Nothing)
propView.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
propView.ReadOnly = True
End Sub