DataGrid Data Entry help

yousuf42

Well-known member
Joined
Feb 12, 2006
Messages
101
Programming Experience
1-3
Dear All,

below mentioned code is working and fetches data exactly as I wanted with one exception. That's, the ProductID, I enter goes into next row. all other data(ProdDescription,Uprice) goes into right cells of currentrow. so what's wrong here? why ProdID goes into next row? can any one figureout this please????

Your help is most appreciated..!

'Form level declaration
VB.NET:
Dim ProdIDTexBox As TextBox
Dim dgtbc As DataGridTextBoxColumn


' Code for a Column in Table Style
VB.NET:
dgtbc = dgInvoice.TableStyles(0).GridColumnStyles(1) '
If Not (dgtbc Is Nothing) Then
dgtbc.Width = 110
dgtbc.HeaderText = " Product ID"
dgtbc.TextBox.CharacterCasing = CharacterCasing.Upper
ProdIDTexBox = dgtbc.TextBox
AddHandler dgtbc.TextBox.Leave, AddressOf CellProdIDLeave  
End If


VB.NET:
Private Sub CellProdIDLeave(ByVal sender As Object, ByVal e As [SIZE=2]System.EventArgs[/SIZE]) 
 
Dim GetProductData As TechManagement.DBComponents.ProductDB = New TechManagement.DBComponents.ProductDB
Dim dtProductDetail As New DataTable
Dim dt As DataTable = DirectCast(dgInvoice.DataSource, DataTable)
 
Dim dr As DataRow = dt.NewRow()
If Not IsDBNull(ProdIDTexBox.Text) = False Or ProdIDTexBox.Text.Length > 2 Then
dtProductDetail = GetProductData.GetProductDetail(ProdIDTexBox.Text)
 
 
dr(2) = dtProductDetail.Rows(0).Item(1).ToString
dr(3) = dtProductDetail.Rows(0).Item(5).ToString
End If
dt.Rows.Add(dr)
End Sub
 
ps; I realised that there was no point making life hard, going through the currency manager when I can just get the grid to do it, using the currentcell property. This isnt the way I would advocate for .NET 2.0, but I have no problems recommending it for .NET 1.1 (cause the currency management is jsut too hidden! :) )
 
Thanks a lot cjard,

I was not at the office. Just I saw your reply. That's a great work.

Hmm.. true, CR doesnt come with the free versions, but I think you may find you can successfully use your VS2003 to design the reports, the free merge modules from CR themselves so your app can display the reports..

I already have CR with VS2003. What I meant was, if I go for VS2005 free version I will loss what I have.

Crystal are a nice bunch.. They give you a trial key for their flagship XI every time you request one (i.e. every time your 30 day trial runs out) and free DLLs to show your reports. If youre that way inclined, you can use Crystal entirely without paying for it.. You dont get any support, but their support is rubbish anyway. (We never bothered buying after the trial because there were too many problems with it, and now use a different reports package)

If you dont mind, What is the better Reports Package?

I never knew an app like what you speak, most the apps ive worked on, the barcode or product id is entered into a separate text box and the lookup result appears in the grid. however, you have chosen to use the grid..

Nice Information!!!. The user wants to enter Qty and sometimes Uprice manually. So, should you recommend to use 2 more textboxes for qty,uprice where the cursor will focus auotomatically after inserting ProductID and Uprice respectively?.

I have seen my way in Oracle eBusiness suit ver 11 for Purchase Orders(i did not see Billing of the same). where user enters ProductID and qty directly into DG.

My application also will be used for Purchase orders, Quotations, Warehouse receiving voucher etc...

I took the bull by the horns and did it for you.

Thank you very much cjard. It is not bull!!. It is really an elephant or a Giant crocodile for me.:) :)

I declared prevCell as

Dim prevCell As DataGridCell = dgInvoice.CurrentCell


I know it is wrong but more than 3 hours now I can't get Dginvoice.Cell (can you show me how to get it please?)

So all my code (cjard's code:D ) goes as here:-

VB.NET:
Private Sub dgInvoice_CurrentCellChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dgInvoice.CurrentCellChanged
 
Dim prevCell As DataGridCell = dgInvoice.CurrentCell
 
If ProdIDTexBox.Text.Length > 2 Then
Try
Select Case prevCell.ColumnNumber
Case 1
Dim GetProductData As TechManagement.DBComponents.ProductDB = New TechManagement.DBComponents.ProductDB
Dim dtProductDetail As DataTable = GetProductData.GetProductDetail( _
dgInvoice.Item(prevCell).ToString())
dgInvoice.Item(prevCell.RowNumber, 2) = _
dtProductDetail.Rows(0)(1)
dgInvoice.Item(prevCell.RowNumber, 4) = _
dtProductDetail.Rows(0)(5)
Case 3
dgInvoice.Item(prevCell.RowNumber, 5) = _
Convert.ToInt32(dgInvoice.Item(prevCell)) * _
Convert.ToInt32(dgInvoice.Item(prevCell.RowNumber, 4))
End Select
prevCell = dgInvoice.CurrentCell
Catch ex As Exception
End Try
End If
 
End Sub

It works wonderfull but after revisiting the same cell only. I know I'm wrong here.i did not declare it correctly!!!.

Can you help me to take that elephant by the horn please.:D (bcz I don know where the horn is)

Thanks a lot in advance
 
Private Sub dgInvoice_CurrentCellChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dgInvoice.CurrentCellChanged

Dim prevCell As DataGridCell = dgInvoice.CurrentCell

Noo.. we cant go and set the previousCell = to the current cell before we start.. Think about it logically! Why would I have called the variable "prevCell" if I was going to immediately assign it to current cell? Surely then, I would have called it "currCell"

The prevCell declaration needs to go at the top of the class. Because it is the last thing we set before we leave the CurrentCell changed event (which occurs after the cell changes) and it needs to be remembered inbetween successive calls to the event handler. As a result, it is guaranteed to be pointing to the previous cell the next time we run this method.

Think about it

You focus cell 0
the currect cell 0
you do some stuff
set prevcel = 0

Now focus cell1
curent cell is now 1, but PREV CELL is still 0
do some stuff with prev cell (0)
then update prevcell = 1


So this way we can tell, whatever cell we are in now, if the previous cell was the prod id column, then we should lookup the product for that prev cell, and put the results in the same row.

Think about it
 
Thanks a lot cjard,

Now i added this.

VB.NET:
Private Sub dgInvoice_CurrentCellChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dgInvoice.CurrentCellChanged
Dim GetProductData As TechManagement.DBComponents.ProductDB = New TechManagement.DBComponents.ProductDB
' Dim dtProductDetail As New DataTable
Dim dt As DataTable = DirectCast(dgInvoice.DataSource, DataTable)
Dim prevCell As DataGridCell '= dgInvoice.CurrentCell 'DirectCast(dgInvoice.CurrentCell, DataGridCell) ' = 'dt.Columns(dgInvoice.CurrentCell.ColumnNumber(1)) '.ColumnName
If dgInvoice.CurrentCell.ColumnNumber = 0 Then
prevCell.ColumnNumber = 0
ElseIf dgInvoice.CurrentCell.ColumnNumber = 1 Then
prevCell.ColumnNumber = 0
ElseIf dgInvoice.CurrentCell.ColumnNumber = 2 Then
prevCell.ColumnNumber = 1
ElseIf dgInvoice.CurrentCell.ColumnNumber = 3 Then
prevCell.ColumnNumber = 2
ElseIf dgInvoice.CurrentCell.ColumnNumber = 4 Then
prevCell.ColumnNumber = 3
ElseIf dgInvoice.CurrentCell.ColumnNumber = 5 Then
prevCell.ColumnNumber = 4
'elseif dginvoice.CurrentCell.ColumnNumber = 
End If
 
Select Case prevCell.ColumnNumber
Case 1
Dim dtProductDetail As DataTable = GetProductData.GetProductDetail( _
dgInvoice.Item(prevCell).ToString())
dgInvoice.Item(prevCell.RowNumber, 2) = _
dtProductDetail.Rows(0)(1)
dgInvoice.Item(prevCell.RowNumber, 4) = _
dtProductDetail.Rows(0)(5)
Case 3
dgInvoice.Item(prevCell.RowNumber, 5) = _
Convert.ToInt32(dgInvoice.Item(prevCell)) * _
Convert.ToInt32(dgInvoice.Item(prevCell.RowNumber, 4))
'Case 5
' dt.NewRow()
End Select
 
prevCell = dgInvoice.CurrentCell
 
End Sub

Am I right?.

After adding newrow, When I pass value to Prodid into newrow cursor goes into previous row?!.

Sorry for taking your valuable time.
 
good grief.. youre making this way too hard..

pray tell, what is that huge block of IFs supposed to do, at the start of the method?
 
Thank you very much cjard for all your efforts, time and sharing your valuable information.

Now I've changed as following and it works fine:-

VB.NET:
Private Sub dgInvoice_CurrentCellChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dgInvoice.CurrentCellChanged ' 
Dim GetProductData As TechManagement.DBComponents.ProductDB = New TechManagement.DBComponents.ProductDB
Dim dt As DataTable = DirectCast(dgInvoice.DataSource, DataTable)
Dim prevCell As DataGridCell prevCell.RowNumber = dgInvoice.CurrentCell.RowNumber
Select Case dgInvoice.CurrentCell.ColumnNumber
Case 0
prevCell.ColumnNumber = 0
Case 1
 
prevCell.ColumnNumber = 0
Case 2
prevCell.ColumnNumber = 1
Case 3
prevCell.ColumnNumber = 2
Case 4
prevCell.ColumnNumber = 3
Case 5
prevCell.ColumnNumber = 4
End Select
 
Select Case prevCell.ColumnNumber
Case 1
Dim dtProductDetail As DataTable = GetProductData.GetProductDetail( _
dgInvoice.Item(prevCell).ToString())
dgInvoice.Item(prevCell.RowNumber, 2) = _
dtProductDetail.Rows(0)(1)
dgInvoice.Item(prevCell.RowNumber, 4) = _
dtProductDetail.Rows(0)(5)
Case 1 Or 2 Or 3
dgInvoice.Item(prevCell.RowNumber, 5) = _
Convert.ToInt32(dgInvoice.Item(prevCell)) * _
Convert.ToInt32(dgInvoice.Item(prevCell.RowNumber, 4))


End Select

 
prevCell = dgInvoice.CurrentCell
End Sub

Thanks a lot....
 
Nooo.. Argh, you clearly dont get it.

This code will only work fine if the user tabs through the grid in left to right order..

Additionally, you have multiple cases that overlap, and you use variables that are not declared..


I gave you the exact, and only code you needed. All you had to do was place one declaration at the top of the class


Here is the entire code for the form, just paste it in:
VB.NET:
Option Strict Off
Imports System.Drawing.Drawing2D
Imports System.Data.OleDb
Imports TechManagement.DBComponents

Public Class frmProdDataEntry
  Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

  Public Sub New()
    MyBase.New()

    'This call is required by the Windows Form Designer.
    InitializeComponent()

    'Add any initialization after the InitializeComponent() call

  End Sub

  'Form overrides dispose to clean up the component list.
  Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
    If disposing Then
      If Not (components Is Nothing) Then
        components.Dispose()
      End If
    End If
    MyBase.Dispose(disposing)
  End Sub

  'Required by the Windows Form Designer
  Private components As System.ComponentModel.IContainer

  'NOTE: The following procedure is required by the Windows Form Designer
  'It can be modified using the Windows Form Designer.  
  'Do not modify it using the code editor.
  Friend WithEvents cmdAddNew As System.Windows.Forms.Button
  Friend WithEvents cmdSave As System.Windows.Forms.Button
  Friend WithEvents cmdDelete As System.Windows.Forms.Button
  Friend WithEvents dgInvoice As TechManagement.DBComponents.myDG
  <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
    Me.components = New System.ComponentModel.Container
    Me.cmdAddNew = New System.Windows.Forms.Button
    Me.cmdSave = New System.Windows.Forms.Button
    Me.cmdDelete = New System.Windows.Forms.Button
    Me.dgInvoice = New TechManagement.DBComponents.myDG(Me.components)
    CType(Me.dgInvoice, System.ComponentModel.ISupportInitialize).BeginInit()
    Me.SuspendLayout()
    '
    'cmdAddNew
    '
    Me.cmdAddNew.Location = New System.Drawing.Point(72, 352)
    Me.cmdAddNew.Name = "cmdAddNew"
    Me.cmdAddNew.Size = New System.Drawing.Size(72, 32)
    Me.cmdAddNew.TabIndex = 60
    Me.cmdAddNew.Text = "Add new"
    '
    'cmdSave
    '
    Me.cmdSave.Location = New System.Drawing.Point(168, 352)
    Me.cmdSave.Name = "cmdSave"
    Me.cmdSave.Size = New System.Drawing.Size(72, 32)
    Me.cmdSave.TabIndex = 61
    Me.cmdSave.Text = "Save"
    '
    'cmdDelete
    '
    Me.cmdDelete.Location = New System.Drawing.Point(256, 352)
    Me.cmdDelete.Name = "cmdDelete"
    Me.cmdDelete.Size = New System.Drawing.Size(72, 32)
    Me.cmdDelete.TabIndex = 62
    Me.cmdDelete.Text = "Delete"
    '
    'dgInvoice
    '
    Me.dgInvoice.DataMember = ""
    Me.dgInvoice.HeaderForeColor = System.Drawing.SystemColors.ControlText
    Me.dgInvoice.Location = New System.Drawing.Point(8, 144)
    Me.dgInvoice.Name = "dgInvoice"
    Me.dgInvoice.Size = New System.Drawing.Size(544, 160)
    Me.dgInvoice.TabIndex = 64
    '
    'frmProdDataEntry
    '
    Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
    Me.ClientSize = New System.Drawing.Size(560, 398)
    Me.Controls.Add(Me.dgInvoice)
    Me.Controls.Add(Me.cmdDelete)
    Me.Controls.Add(Me.cmdSave)
    Me.Controls.Add(Me.cmdAddNew)
    Me.KeyPreview = True
    Me.Name = "frmProdDataEntry"
    Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
    Me.Text = "Product Data Entry"
    CType(Me.dgInvoice, System.ComponentModel.ISupportInitialize).EndInit()
    Me.ResumeLayout(False)

  End Sub

#End Region

  Dim tblTempinvoice As New DataTable
  Dim dgtbc As DataGridTextBoxColumn
  Dim ProdIDTexBox As TextBox
  Dim ProdDesc As New TextBox

  Private prevRow As Integer = 0
  Private prevCell As DataGridCell = Nothing
  Private doLookup As Boolean = False
  Private getProductData As TechManagement.DBComponents.ProductDB = New TechManagement.DBComponents.ProductDB



  Private Sub frmProdDataEntry_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
    customGridStyle()

    prevCell = dgInvoice.CurrentCell
  End Sub

  Private Sub customGridStyle()


    Dim TempInvoiceData As TechManagement.DBComponents.ProductDB = New TechManagement.DBComponents.ProductDB
    Dim DataTableName As String

    tblTempinvoice = TempInvoiceData.Tempinvoice(DataTableName)

    Dim ts As New DataGridTableStyle
    ts.MappingName = DataTableName
    ts.RowHeadersVisible = False
    ts.HeaderBackColor = Color.DarkBlue
    ts.HeaderForeColor = Color.Wheat
    ts.GridLineStyle = DataGridLineStyle.Solid
    ts.GridLineColor = Color.DarkBlue



    Me.dgInvoice.TableStyles.Add(ts)
    Me.dgInvoice.DataSource = tblTempinvoice

    dgtbc = dgInvoice.TableStyles(0).GridColumnStyles(0)
    If Not (dgtbc Is Nothing) Then
      dgtbc.Width = 45
      dgtbc.HeaderText = "S No"
      dgtbc.Alignment = HorizontalAlignment.Center

    End If

    dgtbc = dgInvoice.TableStyles(0).GridColumnStyles(1) '

    If Not (dgtbc Is Nothing) Then

      dgtbc.Width = 110

      dgtbc.HeaderText = "       Product ID"

      dgtbc.TextBox.CharacterCasing = CharacterCasing.Upper
      ProdIDTexBox = dgtbc.TextBox
      'AddHandler dgtbc.TextBox.Leave, AddressOf ProdIDCellLeave ' Change ProdIDTexBox in place of dgtbc


    End If

    dgtbc = dgInvoice.TableStyles(0).GridColumnStyles(2) '
    If Not (dgtbc Is Nothing) Then

      dgtbc.Width = 281
      dgtbc.HeaderText = "                                    Description"
      dgtbc.TextBox.CharacterCasing = CharacterCasing.Upper
      'AddHandler dgtbc.TextBox.Enter, AddressOf DescEnter

      ProdDesc = dgtbc.TextBox
    End If

    dgtbc = dgInvoice.TableStyles(0).GridColumnStyles(3)

    If Not (dgtbc Is Nothing) Then

      dgtbc.Width = 50
      dgtbc.HeaderText = "   Qty"


    End If

    dgtbc = dgInvoice.TableStyles(0).GridColumnStyles(4) '
    If Not (dgtbc Is Nothing) Then
      dgtbc.Width = 90
      dgtbc.HeaderText = "        U Price"
    End If

    dgtbc = dgInvoice.TableStyles(0).GridColumnStyles(5) '
    If Not (dgtbc Is Nothing) Then
      dgtbc.Width = 100
      dgtbc.HeaderText = "        Amount"
    End If


  End Sub








  Private Sub dgInvoice_CurrentCellChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dgInvoice.CurrentCellChanged

    Select Case prevCell.ColumnNumber
      Case 1
        Dim dtProductDetail As DataTable = getProductData.GetProductDetail( _
          dgInvoice.Item(prevCell).ToString())
        dgInvoice.Item(prevCell.RowNumber, 2) = dtProductDetail.Rows(0)(1)
        dgInvoice.Item(prevCell.RowNumber, 4) = dtProductDetail.Rows(0)(5)

      Case 3
        dgInvoice.Item(prevCell.RowNumber, 5) = _
          Convert.ToInt32(dgInvoice.Item(prevCell)) * _
          Convert.ToInt32(dgInvoice.Item(prevCell.RowNumber, 4))

    End Select

    prevCell = dgInvoice.CurrentCell


  End Sub
End Class
 
Back
Top