Announcement

Collapse
No announcement yet.

Deleting A Selected Row - MLG

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Deleting A Selected Row - MLG

    Hello,

    I want to be able to delete a selected row from MLG:

    My effort that isn't working:

    Code:
    Method DeleteUsers(ByVal nCbHndl As Long) As Long
            Local DeleteAns As Long
            Local sRecordNo As String
    
            Control Get Text nCbHndl, %ID_FRMUPDATEUSERS_TXTRECORDNO To sRecordNo
    
            DeleteAns = MsgBox("Record will be deleted permanently." & $CrLf & "Are you sure want to delete this record?", %MB_YESNO Or %MB_ICONINFORMATION, VD_App.Title)
            If DeleteAns = %IDYES Then
               slExe "Begin"
                  SendMessage hUsersGrid,%MLG_GETSELECTED,0,0
                  SendMessage hUsersGrid,%MLG_DELETEROWS,Val(sRecordNo),Val(sRecordNo)
                  SendMessage hUsersGrid,%MLG_REFRESH,1,0
                  slEXE "Delete From tblUsers WHERE RowID = '" + sRecordNo + "'"  
               slExe "End"
               Me.TotalUsersRecords(nCbHndl)
               MsgBox "Record Deleted", %MB_TASKMODAL Or %MB_ICONINFORMATION, VD_App.Title 
               'Users.BrowseAllUsersRecords(nCbHndl)
            End If
    
       End Method
    Any idea pointing me to the right direction would be appreciated.

    Kind regards.
    Fredrick Ughimi
    www.meganetsoft.com

  • #2
    Hi Fredrick!

    Seems like you're using the right API ...here's what I use ...


    Code:
    GridGetCurrentRC : SendMessage hGrid, %MLG_DeleteRows, CurrentRow, CurrentRow : GridRefreshHeaders : GridRefresh
    
    Sub GridGetCurrentRC
    If Debug Then Txt.Print FuncName$
       SendMessage(hGrid, %MLG_GetSelectedEx,VarPtr(CurrentRow),VarPtr(CurrentCol))  'get selected Row/Col
    End Sub
    
    Sub GridRefresh
    If Debug Then Txt.Print FuncName$
       SendMessage hGrid, %MLG_Refresh, 0, 0
    End Sub

    Comment


    • #3
      Hello Gary,

      Thank you for your response and the codes posted.

      Still did not work for me. I wonder what is preventing it from working.

      Code:
       SendMessage(hUsersGrid, %MLG_GetSelectedEx,VarPtr(CurrentRow),VarPtr(CurrentCol))  'get selected Row/Col 
       SendMessage hUsersGrid, %MLG_DeleteRows, VarPtr(CurrentRow),VarPtr(CurrentRow)
       SendMessage hUsersGrid, %MLG_Refresh, 0, 0
      Regards.
      Fredrick Ughimi
      www.meganetsoft.com

      Comment


      • #4
        Remove VarPtr from call to %MLG_DeleteRows so it looks like
        SendMessage hUsersGrid, %MLG_DeleteRows, CurrentRow, CurrentRow ' (see Gary's code above)

        Comment


        • #5
          Ah! Thanks Borje Hagsten.

          I initially erroneously declared CurrentRow as null terminated string (Asciiz).
          Now declared as Dword. Works now.

          Thanks Gary.

          Regards.
          Fredrick Ughimi
          www.meganetsoft.com

          Comment


          • #6
            METHOD DeleteUsers(BYVAL nCbHndl AS LONG) AS LONG
            LOCAL DeleteAns AS LONG
            LOCAL sRecordNo AS STRING

            CONTROL GET TEXT nCbHndl, %ID_FRMUPDATEUSERS_TXTRECORDNO TO sRecordNo

            DeleteAns = MSGBOX("Record will be deleted permanently." & $CRLF & "Are you sure want to delete this record?", %MB_YESNO OR %MB_ICONINFORMATION, VD_App.Title)
            IF DeleteAns = %IDYES THEN
            slExe "Begin"
            SendMessage hUsersGrid,%MLG_GETSELECTED,0,0
            SendMessage hUsersGrid,%MLG_DELETEROWS,VAL(sRecordNo),VAL(sRecordNo)
            SendMessage hUsersGrid,%MLG_REFRESH,1,0
            slEXE "Delete From tblUsers WHERE RowID = '" + sRecordNo + "'"
            slExe "End"
            Me.TotalUsersRecords(nCbHndl)
            MSGBOX "Record Deleted", %MB_TASKMODAL OR %MB_ICONINFORMATION, VD_App.Title
            'Users.BrowseAllUsersRecords(nCbHndl)
            END IF

            END METHOD
            Glad you found the problem.
            Pro: Synching table to grid is definitely fast.
            Con: Grid will not be current at other stations
            Con: Changing grid assumes SQL changes to table will match

            Noticed SQL delete statement followed by 'BrowseAllUserRecords(nCbHndl)
            Does BrowserAllUserRecords reload the grid from the table and redisplay?

            slEXE "Delete From tblUsers WHERE RowID = '" + sRecordNo + "'"
            RowID can change so made RowNum primary key autoincrement in create statement
            RowID is INTEGER so quoting is not needed





            Another way:
            Pro: Everything in synch
            Pro: MLG delete,insert, update eliminated
            Con: Much slower since table reloaded

            Begin transaction
            Update table
            Rollback/exit if inaccurate changecount
            End transaction
            Reload MLG
            Using a virtual grid might be considered.


            Code:
            #INCLUDE "sqlitening.inc"
            FUNCTION PBMAIN () AS LONG
             LOCAL RowNum AS QUAD
             slOpen ":memory:"
             slexe  "create table tblUsers(RowNum integer primary key autoincrement)"
             slexe  "insert into tblusers values(10),(20),(30)"
             rownum = 90  '90 will fail
             slexe  "begin immediate"
             slexe  USING$("delete from tblusers where RowNum=#",RowNum) 'integer used
             IF slGetChangeCount <> 1 THEN                               'check change
              slexe "rollback"                                           'wrong, rollback
              ? "",,"delete failed"
              EXIT FUNCTION
             END IF
             slexe "end"                                                 'commit changes
             'reload MLG                                                 'reload MLG
             ? "",,"deleted 1-record"
            END FUNCTION
            https://duckduckgo.com instead of google

            Comment


            • #7
              Hello Mike,

              Nice to hear from you.

              >>Does BrowserAllUserRecords reload the grid from the table and redisplay?

              No. See my code above again, you can see it is commented out. Its was just something I was trying out before I decided to seek for help.
              Fredrick Ughimi
              www.meganetsoft.com

              Comment


              • #8
                Hello,

                Any idea on how to add values to the next available row in MLG?

                In Listview this is how I used to do it using PwrDev.

                Code:
                  LastRowID = slGetInsertID  ' Returns the rowid key of the most recent insert into the database (SQLitening)
                  ListView Get Count nCbHndl, %ID_FRMLEAVE_LISTVIEW1 To SNo
                  Incr SNo
                  iItem = VD_ListView_Item_Add(nCbHndl, %ID_FRMLEAVE_LISTVIEW1, Format$(LastRowID), 0)  
                  VD_ListView_Item_Text(nCbHndl, %ID_FRMLEAVE_LISTVIEW1, iItem, 1, Format$(SNo))             
                  VD_ListView_Item_Text(nCbHndl, %ID_FRMLEAVE_LISTVIEW1, iItem, 2, sPIN)
                  VD_ListView_Item_Text(nCbHndl, %ID_FRMLEAVE_LISTVIEW1, iItem, 3, sSurname
                Any pointers would greatly be appreciated.

                Fredrick Ughimi
                www.meganetsoft.com

                Comment


                • #9
                  I just don't work with MLG enough to answer. I know the demo has an auto append mode.
                  I have used it only for viewing recordsets.

                  https://duckduckgo.com instead of google

                  Comment


                  • #10
                    Hi Fredrick,

                    I'm not clear on what you mean. Could you clarify what is mean with "next available row"?

                    MLG has API for setting the value of a cell (row,col) - is that not what you're asking to do, but perhaps with row+1, col ?

                    Comment


                    • #11
                      Hello,

                      Mike, I want to do a manual append.

                      Gary, I want to be able to append (MLG_Put) text on the grid on the next available row. For instance:

                      Code:
                      m_sLeaveType = "Normal" 
                      MLG_Put(hLeaveTypeGrid,Row,1, m_sLeaveType,1)
                      This normally changes the header text

                      I edit text on the grid like this which works, thanks to you:
                      Code:
                      SendMessage(hLeaveTypeGrid, %MLG_GetSelectedEx,VarPtr(CurrentRow),VarPtr(CurrentCol)) 
                      MLG_Put(hLeaveTypeGrid,CurrentRow ,2, m_sLeaveType,1)
                      Fredrick Ughimi
                      www.meganetsoft.com

                      Comment


                      • #12
                        Fredrick,

                        if I understand your question about appending correctly. I wrote this function to get the next unused row number.

                        Code:
                        FUNCTION MLG_Get_First_Unused_Row (hGrid AS DWORD) AS LONG
                        ' Get First unused row, at Bottom of table
                        ' Returns row number of unsued row, or 0 if none are found.
                        ' Does not check for Gaps between rows Assumes first row with content from bottom
                        ' as the last row.
                        LOCAL lCnt, lRow, lCol AS LONG
                        LOCAL dResult AS DWORD
                        DIM s() AS LOCAL STRING
                        dResult= SendMessage(hGrid, %MLG_GETROWCOLTOT, 0, 0)    ' Get Total Rows and Cols
                        lRow = LO(WORD,dResult) : lCol = HI(WORD,dResult)       ' of current grid
                            'MSGBOX FORMAT$(lCol) + "   " + FORMAT$(lRow)               ' for debug
                            FOR lCnt = lRow TO 1  STEP - 1                      ' loop from bottom row to top
                              REDIM s(lCnt TO lCnt,1 TO lCol)                   ' Dim the row we want.
                              MLG_GetEx hGrid,s()                               ' get the whole row
                                IF  JOIN$(s(),"") <> "" THEN                    ' Check if row not empty
                                    IF lCnt = lRow THEN EXIT FUNCTION           ' none found function will be 0
                                    FUNCTION = lCnt + 1                         ' previous was the first empty row.
                                    EXIT FUNCTION
                                END IF
                            NEXT lCnt
                            FUNCTION = 1                                        ' All Empty so row 1 is first empty row.
                        END FUNCTION
                        You use it like this.

                        Code:
                        CurrentRow = MLG_Get_First_Unused_Row (hLeaveTypeGrid)
                        MLG_Put(hLeaveTypeGrid,CurrentRow ,2, m_sLeaveType,1)

                        Comment


                        • #13
                          Looks good.

                          Fredrick will notice the limit of LO(Word) ( 0 to 65535 rows)
                          Could grid be resized if a row is deleted or added with decent performance (no blank rows?)
                          This way the row number of the grid is of no concern and the primary key of the table is displayed.

                          Suggestion:
                          This looks ideal for a virtual grid.
                          All changes are done first to SQLite table and 1-page of grid is redisplayed (if needed.)
                          Doing it this way eliminates updating, deleting or inserting to the grid, just refresh a page.
                          Since only a single record is changed the updating of the sql table and refresh of 1-page could be even faster.

                          This keeps the grid in synch with the table.
                          This also prevents assuming all changes to the grid will not fail when updating the SQLite table.
                          If a fail updating the table should occur (duplicate record, not found, etc...) all entries into the grid must be reversed.
                          Another huge benefit is this would work in a multi-user network. An in-memory grid shouldn't be assumed to be current.

                          Personally, I would not edit a grid column.
                          If a column is selected, have a form available for the row or a form for each column (as user changes column.)

                          I would post an example using MLG in virtual mode if I knew how.
                          In the long run this might be a better way to go since you are using SQLite recordsets
                          The record limit can also be a QUAD or greater using a virtual grid if an array is not dimmed to hold each record.

                          If this was a single-user flat file database then the virtual method might not be appropriate since everything can be done in memory


                          https://duckduckgo.com instead of google

                          Comment


                          • #14
                            Hello Rod,

                            Thank you for your response and the codes posted.

                            I tested it. It just replaces the header title. Here is it. This might give you an idea of what I want to achieve:

                            Code:
                            Function MLG_Get_First_Unused_Row (hGrid As Dword) As Long
                            ' Get First unused row, at Bottom of table
                            ' Returns row number of unsued row, or 0 if none are found.
                            ' Does not check for Gaps between rows Assumes first row with content from bottom
                            ' as the last row.
                            Local lCnt, lRow, lCol As Long
                            Local dResult As Dword
                            Dim s() As Local String
                            dResult= SendMessage(hGrid, %MLG_GETROWCOLTOT, 0, 0)    ' Get Total Rows and Cols
                            lRow = Lo(Word,dResult) : lCol = Hi(Word,dResult)       ' of current grid
                                'MSGBOX FORMAT$(lCol) + "   " + FORMAT$(lRow)               ' for debug
                                For lCnt = lRow To 1  Step - 1                      ' loop from bottom row to top
                                  ReDim s(lCnt To lCnt,1 To lCol)                   ' Dim the row we want.
                                  MLG_GetEx hGrid,s()                               ' get the whole row
                                    If  Join$(s(),"") <> "" Then                    ' Check if row not empty
                                        If lCnt = lRow Then Exit Function           ' none found function will be 0
                                        Function = lCnt + 1                         ' previous was the first empty row.
                                        Exit Function
                                    End If
                                Next lCnt
                                Function = 1                                        ' All Empty so row 1 is first empty row.
                            End Function
                            
                            Method SavLeaveType(ByVal nCbHndl As Long) As Long
                                    Local SaveAns&
                                    Local Errorcode&
                            
                                    m_sLeaveType = VD_GetText (nCbHndl, %ID_FRMDEFINELEAVETYPE_TXTLEAVETYPE) 
                                    If Trim$(m_sLeaveType) = "" Then
                                         MsgBox "Please, Enter Leave Type", %MB_TASKMODAL Or %MB_ICONINFORMATION, VD_App.Title
                                         Control Set Focus nCbHndl, %ID_FRMDEFINELEAVETYPE_TXTLEAVETYPE
                                         Exit Method
                                    End If
                            
                                    slExe "Begin"
                                        Errorcode& = slExe(slBuildInsertOrUpdate("tblLeaveType", m_sLeaveType),"E")
                                    slExe "End"
                            
                                    If Errorcode& = 19 Then
                                         MsgBox "Leave Type Already Exist", %MB_TASKMODAL Or %MB_ICONINFORMATION, VD_App.Title  
                                         Control Set Focus nCbHndl, %ID_FRMDEFINELEAVETYPE_TXTLEAVETYPE
                                         Exit Method
                                    End If
                            
                                    If slGetChangeCount = 0 Then
                            
                                        ? "Record Not Saved!", %MB_TASKMODAL Or %MB_ICONINFORMATION, VD_App.Title 
                            
                                        Exit Method
                            
                                    Else  
                            
                                        CurrentRow = MLG_Get_First_Unused_Row (hLeaveTypeGrid)
                                        MLG_Put(hLeaveTypeGrid,CurrentRow ,1, m_sLeaveType,1)
                            
                                        Me.TotalLeaveTypeRecords(nCbHndl)
                            
                                        SaveAns& = MsgBox("Record Saved:" & $CrLf & "Add another record?", %MB_YESNO Or %MB_ICONQUESTION, VD_App.Title)
                            
                                        If SaveAns = %IDYES Then
                                            Me.ClearLeaveType(nCbHndl)
                                        ElseIf SaveAns = %IDNo Then
                                            VD_FormClose(nCbHndl)
                            
                                        End If
                            
                                End If    
                            
                              End Method

                            Hello Mike,

                            >>Since only a single record is changed the updating of the sql table and refresh of 1-page could be even faster.

                            I get what you mean. I initially tried using %MLG_REFRESH which doesn't refresh the grid content. I then proceeded to reloading
                            the content of the grid after saving a record, which looks weird sometimes. The user sudenly sees all records
                            on the grid instead of the record just entered. Except if there is a way to reload just the record entered.




                            Fredrick Ughimi
                            www.meganetsoft.com

                            Comment


                            • #15
                              Fredrick,
                              I tested it. It just replaces the header title
                              Not enough code shown, to trouble shoot.

                              this can happen when Handle = 0

                              what is the Handle of your grid? hLeaveTypeGrid? is it a global? if not Are you passing it to your method?
                              how did you define the grid?

                              Code:
                                CONTROL ADD "MYLITTLEGRID", hDlg, %IDC_MLGGRID1, "z1/h3/e3/r12/c10/b3/s11/x115,115,115,115,115,115,115,115,115,115,115", 0, 0, 810, 150, %MLG_STYLE
                                CONTROL HANDLE hDlg, %IDC_MLGGRID1 TO hGrid1

                              Comment


                              • #16
                                Hello Rod,

                                >>what is the Handle of your grid? hLeaveTypeGrid? is it a global? if not Are you passing it to your method? how did you define the grid?

                                The handle of my grid is hLeaveTypeGrid. Yes it is global. This is how I defined my grid: Control Handle nCbHndl, %ID_FRMDEFINELEAVETYPE_USERCONTROL1 To hLeaveTypeGrid. I am using PwrDev IDE.
                                Fredrick Ughimi
                                www.meganetsoft.com

                                Comment


                                • #17
                                  CurrentRow was defined as Dword?

                                  Instance CurrentRow as Dword.

                                  Fredrick Ughimi
                                  www.meganetsoft.com

                                  Comment


                                  • #18
                                    Fredrick,
                                    I use CurrentRow as Long in my code.

                                    Comment


                                    • #19
                                      Fredrick,

                                      Did you check if your are getting the values expected by putting a temporary msgbox?

                                      Code:
                                      Else  
                                      
                                                  CurrentRow = MLG_Get_First_Unused_Row (hLeaveTypeGrid)
                                      msgbox "Grid Handle : " + format$(hLeaveTypeGrid) + $crlf + "Empty Row : " + format$(CurrentRow)
                                                  MLG_Put(hLeaveTypeGrid,CurrentRow ,1, m_sLeaveType,1)
                                      
                                                  Me.TotalLeaveTypeRecords(nCbHndl)

                                      Comment


                                      • #20
                                        Here is the code I used to test. I my help you see what you are doing different.

                                        Code:
                                        #COMPILE EXE
                                        #DIM ALL
                                        
                                        %USEMACROS = 1
                                        %MLGSLL = 1
                                        #INCLUDE "Win32API.inc"
                                        #INCLUDE "MLG.INC"
                                        #LINK "MLG.SLL"
                                        
                                        %IDC_MLGGRID1 = 101
                                        %BTN_BUTTON1 = 102
                                        %BTN_BUTTON2 = 103
                                        %BTN_BUTTON3 = 104
                                        
                                        GLOBAL hGrid1 AS DWORD
                                        
                                        FUNCTION PBMAIN () AS LONG
                                        
                                             LOCAL result AS LONG
                                             result=ShowOneGrid(0)
                                        
                                        END FUNCTION
                                        
                                        FUNCTION ShowOneGrid(hDlg AS LONG) AS LONG
                                        LOCAL lCnt1, lCnt2 AS LONG
                                        
                                          MLG_Init
                                          DIALOG NEW 0, "Test",,, 830, 250, %WS_POPUP OR %WS_BORDER OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
                                            %WS_MINIMIZEBOX OR %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR _
                                            %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                                        
                                          CONTROL ADD "MYLITTLEGRID", hDlg, %IDC_MLGGRID1, "z1/h3/e3/r12/c10/b3/s11/x115,115,115,115,115,115,115,115,115,115,115", 0, 0, 810, 150, %MLG_STYLE
                                          CONTROL ADD BUTTON, hDlg, %BTN_BUTTON1, "MLG_Put", 15, 220, 60, 13
                                          CONTROL ADD BUTTON, hDlg, %BTN_BUTTON2, "MLG_PutEX", 95, 220, 60, 13
                                          CONTROL ADD BUTTON, hDlg, %BTN_BUTTON3, "Get Empty row", 195, 220, 60, 13
                                          CONTROL HANDLE hDlg, %IDC_MLGGRID1 TO hGrid1
                                        
                                          FOR lCnt1 = 1 TO 5
                                            FOR lCnt2 = 1 TO 10
                                             MLG_PUT hGrid1,lCnt1,lCnt2,"Text " + FORMAT$(lCnt1)+ "-" + FORMAT$(lCnt2),0
                                            NEXT lCnt2
                                          NEXT lCnt1
                                        
                                           DIALOG SHOW MODAL hDlg CALL ShowOneGridProc
                                        
                                        END FUNCTION
                                        
                                        CALLBACK FUNCTION ShowOneGridProc()
                                          LOCAL I AS long
                                          LOCAL s AS STRING
                                          LOCAL s() AS STRING
                                        
                                          SELECT CASE CBMSG
                                             CASE %WM_COMMAND
                                              ' Process control notifications
                                              SELECT CASE AS LONG CB.CTL
                                                CASE %BTN_BUTTON1
                                                  IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                                  MLG_PUT hGrid1,5,5,"hello" ,1
                                                  END IF
                                        
                                                CASE %BTN_BUTTON2
                                                  IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                                    i = 9
                                                    REDIM s(i TO i, 1 TO 10) AS STRING
                                                     s(i, 1) = "Hello1"
                                                     s(i, 2) = "Hello2"
                                                     s(i, 3) = "Hello3"
                                                     s(i, 4) = "Hello4"
                                                     s(i, 5) = "Hello5"
                                                     s(i, 6) = "Hello6"
                                                     s(i, 7) = "Hello7"
                                                     s(i, 8) = "Hello8"
                                                     s(i, 9) = "Hello9"
                                                     s(i, 10) = "Hello10"
                                                  MLG_PUTEX hGrid1,s(), 4,1
                                                  END IF
                                        
                                                CASE %BTN_BUTTON3
                                                  IF CB.CTLMSG = %BN_CLICKED OR CB.CTLMSG = 1 THEN
                                                   i = MLG_Get_First_Unused_Row (hGrid1)
                                                   'msgbox "Grid Handle : " + format$(hGrid1) + $crlf + "Empty Row : " + format$(i)         ' for debuging uncomment.
                                                    IF i <> 0 THEN
                                                     REDIM s(i TO i, 1 TO 10) AS STRING
                                                      s(i, 1) = "Added1"
                                                      s(i, 2) = "Added2"
                                                      s(i, 3) = "Added3"
                                                      s(i, 4) = "Added4"
                                                      s(i, 5) = "Added5"
                                                      s(i, 6) = "Added6"
                                                      s(i, 7) = "Added7"
                                                      s(i, 8) = "Added8"
                                                      s(i, 9) = "Added9"
                                                      s(i, 10) = "Added10"
                                                     MLG_PUTEX hGrid1,s(), 4,1
                                                   END IF
                                                  END IF
                                                END SELECT
                                          END SELECT
                                        
                                        END FUNCTION
                                        
                                        
                                        FUNCTION MLG_Get_First_Unused_Row (hGrid AS DWORD) AS LONG
                                        ' Get First unused row, at Bottom of table
                                        ' Returns row number of unsued row, or 0 if none are found.
                                        ' Does not check for Gaps between rows Assumes first row with content from bottom
                                        ' as the last row.
                                        LOCAL lCnt, lRow, lCol AS LONG
                                        LOCAL dResult AS DWORD
                                        DIM s() AS LOCAL STRING
                                        dResult= SendMessage(hGrid, %MLG_GETROWCOLTOT, 0, 0)    ' Get Total Rows and Cols
                                        lRow = LO(WORD,dResult) : lCol = HI(WORD,dResult)       ' of current grid
                                            'MSGBOX FORMAT$(lCol) + "   " + FORMAT$(lRow)               ' for debug
                                            FOR lCnt = lRow TO 1  STEP - 1                      ' loop from bottom row to top
                                              REDIM s(lCnt TO lCnt,1 TO lCol)                   ' Dim the row we want.
                                              MLG_GetEx hGrid,s()                               ' get the whole row
                                                IF  JOIN$(s(),"") <> "" THEN                    ' Check if row not empty
                                                    IF lCnt = lRow THEN EXIT FUNCTION           ' none found function will be 0
                                                    FUNCTION = lCnt + 1                         ' previous was the first empty row.
                                                    EXIT FUNCTION
                                                END IF
                                            NEXT lCnt
                                            FUNCTION = 1                                        ' All Empty so row 1 is first empty row.
                                        END FUNCTION

                                        Comment

                                        Working...
                                        X