MySql revisited

General Help regarding HMG, Compilation, Linking, Samples

Moderator: Rathinagiri

User avatar
BeGeS
Posts: 125
Joined: Fri Jul 14, 2017 10:45 am
DBs Used: DBF
Location: La Mancha, Spain

Re: MySql revisited

Post by BeGeS »

dragancesu wrote: Tue Aug 08, 2017 11:25 am I know that many would like to create and see how a program uses a MySQL database
I am one of them.

For many years I have wanted to learn / work with SQL. I have never had the opportunity or the means... until now.

Although I must first soak up HMG.

Thank you so much, Dragan.
I get by with a little help from my friends
User avatar
serge_girard
Posts: 3158
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: MySql revisited

Post by serge_girard »

Hello,

I made a little demo which shows the difference between working with DBF-files and MySQl.
The meaning is to demonstrate how to calculate an total-amount by grouping on 2 fields.

Structure:
------------
SHOP_ID Num 12
REC_DATE Date
TOTAL Num 12.2
...

Both have the same structure and are the same (demonstration purpose). The content is some
thousands of records which need to be sorted by SHOP_ID + REC_DATE and equal keys are to be
summed.

In SQL I do this as following:

Code: Select all

SELECT SHOP_ID, REC_DATE, SUM(TOTAL) FROM F0001  
WHERE REC_DATE >= '2017-04-27'                    
AND   SHOP_ID IN (1,2,4,6,7,9,10)                
GROUP BY SHOP_ID, REC_DATE                        
ORDER BY 1,2                                      
In order to get the same result in DBF one should use the technique of grouping by key
(see the 3 DO WHILE structures). There may be some other commands
(like: TOTAL ON <expKey> [FIELDS <idField list>] TO <xcDatabase> [<scope>] [WHILE <lCondition>] [FOR <lCondition>] )
But to be honest: I don't like them and have alway avoid them!

Output is something like this:
1 27/04/2017 1388.83
1 28/04/2017 1906.39
....


So here's the code!
Have fun with SQL, Serge

Code: Select all

 
 #include "hmg.ch"



FUNCTION MAIN()
/**************/
PUBLIC dbo


SET PRINTER TO C:\TEST\GF0001.TXT   
SET PRINTER ON 
SET CONSOLE OFF

pHOST    := 'your_host'
pDBUSER  := 'your_user'
pDBPW    := 'your_password'
pDBNAME  := 'your_dbname'

IF SQL_Connect(pHOST,pDBUSER,pDBPW,pDBNAME) == Nil 
	MSGINFO("Not connected to SQL server! " , 'NOK')
	RETURN 
ENDIF

cQuery1	:= " SELECT SHOP_ID, REC_DATE, SUM(TOTAL) FROM F0001 "  
cQuery1	+= " WHERE REC_DATE >= '2017-04-27' "
cQuery1	+= " AND   SHOP_ID IN (1,2,4,6,7,9,10) "
cQuery1	+= " GROUP BY SHOP_ID, REC_DATE  "   
cQuery1	+= " ORDER BY 1,2  "
cSQL		:= cQuery1 
cQuery1 	:= dbo:Query( cQuery1  )
IF cQuery1:NetErr()					// hier fout			
   MSGINFO('SQL ' +  cQuery1:Error()  , cSQL )
   RETURN 
ENDIF

i := 1
DO WHILE i <= cQuery1:LastRec() 
   aCurRow1       := cQuery1:GetRow(i)
   nSHOP_ID       := aCurRow1:fieldGet(1)
   dREC_DATE      := aCurRow1:fieldGet(2)
   nTOTAL         := aCurRow1:fieldGet(3)
   ? nSHOP_ID, dREC_DATE, nTOTAL
   i++
ENDDO 
dbo:Destroy()
 


? '*******************'
USE  P:\STAT\F0001 
SET FILTER TO REC_DATE >= CTOD('27/04/2017') .AND. ( SHOP_ID == 1 .OR. SHOP_ID == 2   .OR. SHOP_ID == 4 .OR. SHOP_ID == 6 .OR. SHOP_ID == 7 .OR. SHOP_ID == 9 .OR. SHOP_ID == 10)
GO TOP
INDEX ON STR(SHOP_ID,2,0) + SUBSTR(DTOC(REC_DATE),7,4) + SUBSTR(DTOC(REC_DATE),4,2) + SUBSTR(DTOC(REC_DATE),1,2) TO iF0001
GO TOP
 
DO WHILE .NOT. EOF()
   nSHOP_ID := F0001->SHOP_ID

   DO WHILE .NOT. EOF() .AND.  nSHOP_ID == F0001->SHOP_ID
      dREC_DATE   := F0001->REC_DATE
      nTOTAL      := 0.00

      DO WHILE .NOT. EOF() .AND.  nSHOP_ID == F0001->SHOP_ID .AND. dREC_DATE == F0001->REC_DATE
         nTOTAL   := nTOTAL   + F0001->TOTAL   
         SKIP
      ENDDO
      ? nSHOP_ID, dREC_DATE, nTOTAL
   ENDDO
ENDDO

SET PRINTER TO    
SET PRINTER OFF
SET CONSOLE ON
CLOSE ALL
RETURN






FUNCTION SQL_Connect(host,user,password,dbname)
/*********************************************/
dbo := tmysqlserver():new(AllTrim(host),AllTrim(user),AllTrim(password))
IF dbo:NetErr()
   msginfo(dbo:ERROR())
   RETURN nil
ENDIF

dbo:selectdb(dbname)
IF dbo:NetErr()
   msginfo(dbo:ERROR())
   RETURN nil
ENDIF

RETURN dbo


 
There's nothing you can do that can't be done...
User avatar
serge_girard
Posts: 3158
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: MySql revisited

Post by serge_girard »

Here is another one (with PDF printing):

Code: Select all

#include "hmg.ch"

 

FUNCTION MAIN()
/***************/
PUBLIC dbo

PUBLIC pHOST	:= 'hostname'
PUBLIC pDBUSER	:= 'user'
PUBLIC pDBPW	:= 'pasword'
PUBLIC pDBNAME	:= 'dbname'

SET CENT ON
SET DATE FRENCH

If !IsWIndowActive (Form_1) 

   DEFINE WINDOW Form_1 ;
      AT 0,0 ;
      WIDTH  600 ;		 
      HEIGHT 600;	 
      TITLE 'Personel' ;
      BACKCOLOR SILVER ;
      MAIN ;
      ICON  "images\form_1.ico"	

      ON KEY ESCAPE		ACTION {  Form_1.Release }
      ON KEY F1			ACTION {  Form_1.Release }
      
      DEFINE GRID Grid_Personel
         ROW 10
         COL 10
         WIDTH  580
         HEIGHT 400
         FONTNAME "Arial" 
         FONTSIZE 10 
         HEADERS {'ID', 'Department', 'Name' , 'Family name', 'Salary'  } 
         WIDTHS  {50        , 100,       120,      120               ,   70     }
         JUSTIFY {GRID_JTFY_LEFT, GRID_JTFY_LEFT, GRID_JTFY_LEFT, GRID_JTFY_LEFT, GRID_JTFY_RIGHT    }
         ITEMS Load_Personel()
      END GRID     

      DEFINE BUTTON BT_1 
         PARENT Form_1 
         ROW    440
         COL    10
         WIDTH  70
         HEIGHT 70
         ACTION  {Print_Personel()}
         CAPTION ""
         TRANSPARENT .T.
         TOOLTIP 'Print PDF'
         PICTURE "HP_PRINT"
         PICTALIGNMENT TOP
      END BUTTON

   END WINDOW

   CENTER WINDOW   Form_1

   ACTIVATE WINDOW Form_1

ELSE
   Form_1.SetFocus  
ENDIF
 
RETURN NIL





FUNCTION Print_Personel()
/******************************/
PUBLIC cPDF  := 'PERSONEL.PDF'

IF SQL_Connect(pHOST, pDBUSER, pDBPW, pDBNAME)  == Nil         // geen connectie
   MSGINFO('No SQL connection', 'NOK' )		 
   RETURN
ENDIF

cQuery1	:= " SELECT PERS_ID, DEPT, NAME, FAMILY_NAME, SALARY  "  
cQuery1	+= " FROM   PERSONEL     " 
cQuery1	+= " WHERE  ACTIVE =  'J'    " 
cQuery1	+= " ORDER  BY 2,4,3 " 
cQuery1	:= dbo:Query( cQuery1 )

IF cQuery1:NetErr()                                          
   MSGINFO(cQuery1:Error(), 'NOK' )	
   RETURN
ENDIF


Personel_PDF_INIT()
Personel_PDF_CREATE()
Personel_PDF_END()

dbo:Destroy()

EXECUTE FILE cPDF    

RETURN




FUNCTION Personel_PDF_INIT()
/**********************************************/
LOCAL lSuccess       := .F.
PUBLIC nCurrentPage  := 1   

SELECT HPDFDOC cPDF TO lSuccess PAPERSIZE HPDF_PAPER_A4
SET HPDFDOC COMPRESS ALL


SET HPDFDOC PASSWORD OWNER "XPASSWORD"
SET HPDFDOC PERMISSION TO COPY
SET HPDFDOC PERMISSION TO PRINT


SET HPDFINFO AUTHOR      TO "PERSONEL FILE"
SET HPDFINFO CREATOR     TO "PERSONEL FILE"
SET HPDFINFO TITLE       TO "PERSONEL FILE"
SET HPDFINFO SUBJECT     TO "PERSONEL FILE"
SET HPDFINFO KEYWORDS    TO "PERSONEL FILE"
SET HPDFINFO DATECREATED TO DATE() TIME TIME()

IF lSuccess
   nCurrentPage   := 1
   START HPDFDOC
ENDIF     

RETURN






FUNCTION Personel_PDF_END()
/***************************/
nROW  := nROW + 5
 
END HPDFPAGE
END HPDFDOC

RETURN







 
FUNCTION Personel_PDF_CREATE()
/******************************/
LOCAL i 

PUBLIC nROW           := 30
PUBLIC nMAX_ROW       := 260  
PUBLIC nTOT_SALARY    := 0 
PUBLIC nDEPT_SALARY   := 0 

START HPDFPAGE
	SET HPDFDOC ENCODING TO "WinAnsiEncoding"

   Prt_HDR_Personel_PDF()  

   i := 1
   DO WHILE i <= cQuery1:LastRec() 
      aCurRow1       := cQuery1:GetRow(i)

      cDEPT          := aCurRow1:fieldGet(2)
      cKEY           := aCurRow1:fieldGet(2)
      nDEPT_SALARY   := 0

      Prt_Detail1_PDF( 'Department: ' + cDEPT, 5) 
      nROW     := nROW + 5

     
      DO WHILE i <= cQuery1:LastRec()  .AND. cDEPT == cKEY

         cNAME          := aCurRow1:fieldGet(3)
         cFAMILY_NAME   := aCurRow1:fieldGet(4)
         nSALARY        := aCurRow1:fieldGet(5)   
         cNAME          := STRTRAN(cNAME, "''", "'" )  // names like d''artagnan --> d'artagnan
         cFAMILY_NAME   := STRTRAN(cFAMILY_NAME, "''", "'" )

         Prt_Detail1_PDF( ALLTRIM(STR(aCurRow1:fieldGet(1))), 5) 
         Prt_Detail1_PDF( cNAME, 20) 
         Prt_Detail1_PDF( cFAMILY_NAME, 60) 
         Prt_Detail1_PDF( ALLTRIM(STR(aCurRow1:fieldGet(5))), 160 ,'R' ) 

         nROW           := nROW + 5
         nTOT_SALARY    := nTOT_SALARY + nSALARY
         nDEPT_SALARY   := nDEPT_SALARY + nSALARY
         NEWPAGE()
         
         i++
         aCurRow1       := cQuery1:GetRow(i)
         cKEY           := aCurRow1:fieldGet(2)
      ENDDO  
       
      NEWPAGE()
       
      Prt_Detail1_PDF( 'TOTAL Department: ' + cDEPT, 5) 
      Prt_Detail1_PDF( ALLTRIM(STR(nDEPT_SALARY)), 160 ,'R'  )
      nROW              := nROW + 10 
   ENDDO


   NEWPAGE()

   nROW        := nROW + 10 
   Prt_Detail1_PDF( 'TOTAAL Personel', 5   )
   Prt_Detail1_PDF( ALLTRIM(STR(nTOT_SALARY)), 160 ,'R'  )
 
      

RETURN




FUNCTION Prt_Detail1_PDF( cDET, nCOL, cLR ) 
/*****************************************/
DEFAULT cLR    := 'LEFT'

IF cLR == 'LEFT'
   @  nROW ,  nCOL        HPDFPRINT  cDET    SIZE 8     
ELSE
   @  nROW ,  nCOL        HPDFPRINT  cDET    SIZE 8   RIGHT  
ENDIF

RETURN NIL





FUNCTION Prt_HDR_Personel_PDF()   
/*******************************/
nROW     := 30

@ 7,5    HPDFPRINT "Personel file" SIZE 9 COLOR RED  
@ 7,160  HPDFPRINT DTOC(DATE()) + ' ' + 'Page ' + ALLTRIM(STR(nCurrentPage))   SIZE 8 COLOR RED  RIGHT
@ 1, 1   HPDFPRINT RECTANGLE TO 18, 200 PENWIDTH 0 COLOR BLACK ROUNDED
nCurrentPage++ 

Prt_HDR_HDR_Personel() 

NEWPAGE()

IF nTOT_SALARY # 0
   NEWPAGE()
   Prt_Detail1_PDF( 'Transfer', 110, 'R')
   Prt_Detail1_PDF( ALLTRIM(STR(nDEPT_SALARY)), 160 ,'R'  )
   nROW := nROW + 10
ENDIF
RETURN NIL




FUNCTION Prt_HDR_HDR_Personel() 
/*************************************/
NEWPAGE()
Prt_Detail1_PDF( 'ID', 5) 
Prt_Detail1_PDF( 'Name', 20) 
Prt_Detail1_PDF( 'Family name', 60) 
Prt_Detail1_PDF( 'Salary', 160,'R') 
  
nROW := nROW + 10 
 
RETURN NIL






 

FUNCTION NEWPAGE()
/************************/

IF nROW >= nMAX_ROW
 
   Prt_Detail1_PDF( 'Transfer', 110, 'R')
   Prt_Detail1_PDF( ALLTRIM(STR(nDEPT_SALARY)), 160 ,'R'  )

   END HPDFPAGE

   START HPDFPAGE
      Prt_HDR_Personel_PDF()  
ENDIF
RETURN

 




FUNCTION SQL_Connect(XHOST,XDBUSER,XDBPW,XDBNAME)
/**********************************************/
dbo := tmysqlserver():new(ALLTRIM(XHOST),ALLTRIM(XDBUSER),ALLTRIM(XDBPW))
IF dbo:NetErr()
   RETURN nil
ENDIF

IF!EMPTY(XDBNAME) 
   dbo:selectdb(XDBNAME)
   IF dbo:NetErr()
      RETURN nil
   ENDIF
ENDIF
 
RETURN dbo





FUNCTION Load_Personel()
/************************/
IF SQL_Connect(pHOST, pDBUSER, pDBPW, pDBNAME)  == Nil          
   MSGINFO('NO SQL connection', 'NOK' )		 
   RETURN
ENDIF

cQuery1	:= " SELECT ID, DEPARTMENT, NAME, FAMILY_NAME, SALARY  "  
cQuery1	+= " FROM   PERSONEL     " 
cQuery1	+= " WHERE  ACTIVE =  'J'    " 
cQuery1	+= " ORDER  BY 2,4,3   " 
cQuery1	:= dbo:Query( cQuery1 )

IF cQuery1:NetErr()                                          
   MSGINFO(cQuery1:Error(), 'NOK' )	
   RETURN
ENDIF

aPersonel  := {}
FOR i := 1 To cQuery1:LastRec()
   aCurRow1       := cQuery1:GetRow(i)
   cNAME          := aCurRow1:fieldGet(3)
   cFAMILY_NAME   := aCurRow1:fieldGet(4)
   cNAME          := STRTRAN(cNAME, "''", "'" )
   cFAMILY_NAME   := STRTRAN(cFAMILY_NAME, "''", "'" )
   AADD(aPersonel  , { aCurRow1:fieldGet(1), aCurRow1:fieldGet(2) , cNAME, cFAMILY_NAME, aCurRow1:fieldGet(5) }  )
NEXT i

dbo:Destroy() 
RETURN aPersonel
Have fun !
Serge
There's nothing you can do that can't be done...
User avatar
dragancesu
Posts: 920
Joined: Mon Jun 24, 2013 11:53 am
DBs Used: DBF, MySQL, Oracle
Location: Subotica, Serbia

Re: MySql revisited

Post by dragancesu »

Serge, your programs is OK but I think that you hurry with this demo programs.

This is for beginers, can you send backup of your table, and explain how import data?
User avatar
dragancesu
Posts: 920
Joined: Mon Jun 24, 2013 11:53 am
DBs Used: DBF, MySQL, Oracle
Location: Subotica, Serbia

Re: MySql revisited

Post by dragancesu »

Further, it will be difficult to go without data, the basic command is SELECT and the data must exist

Visit the site
Http://www.mysqltutorial.org/mysql-sample-database.aspx
Where you can download demo data mysql sample database in zip format

Unpack sampledatabase.zip and get sampledatabase.sql
It's a plain text file that you can look at using your editor

You will see that at the beginning there are CREATE TABLE commands
And later INSERT INTO, look at it and later it will be explained what it is

The USE `classicmodels` command is important here; You see it in line 28

If you use HeidiSQL, log in as root and create database classicmodels

The next step is File-> Load SQL file ... and select sampledatabase.sql

The contents will be displayed in the Query window, select Execute SQL (F9) and wait, the data tables will be created very quickly, the description you find on the page
User avatar
serge_girard
Posts: 3158
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: MySql revisited

Post by serge_girard »

Hello Dragan,

I know it is for beginners but beginners are always eager to see some fast results...

This one can use for inserting mass (a bit slow beacuse of the possibilties of duplicate keys:

Code: Select all

USE  F0001 
INDEX ON STR(SHOP_ID,2,0) + SUBSTR(DTOC(REC_DATE),7,4) + SUBSTR(DTOC(REC_DATE),4,2) + SUBSTR(DTOC(REC_DATE),1,2) TO iF0001
GO TOP
 
DO WHILE .NOT. EOF()

   cQuery1	:= " INSERT INTO F0001 "  
   cQuery1	+= " (SHOP_ID, KAP_NR, KORT_NR, BEDRAGK, UUR, REC_DATE, VERKOOP, EX_VERK, TOTAL) VALUES( "
   cQuery1	+= " '" + STR(F0001->SHOP_ID) + "',  "  
   cQuery1	+= " '" + STR(F0001->KAP_NR)  + "',  "  
   cQuery1	+= " '" + STR(F0001->KORT_NR) + "',  "  
   cQuery1	+= " '" + STR(F0001->BEDRAGK) + "',  "  
   cQuery1	+= " '" + STR(F0001->UUR)     + "',  "  
   cQuery1	+= " '" + DATE2SQL(F0001->REC_DATE)     + "',  "  
   cQuery1	+= " '" + STR(F0001->VERKOOP) + "',  "  
   cQuery1	+= " '" + STR(F0001->EX_VERK) + "',  "  
   cQuery1	+= " '" + STR(F0001->TOTAL)   + "')  "  
   cSQL		:= cQuery1 
   cQuery1 	:= dbo:Query( cQuery1  )
   IF cQuery1:NetErr()					// hier fout			
      IF 'DUPLICATE' $ UPPER(cQuery1:Error())
         // IGNORE
      ELSE
         MSGINFO('SQL ' +  cQuery1:Error()  , cSQL )
         RETURN 
      ENDIF
   ENDIF
   SKIP
ENDDO
CLOSE ALL
SQL Table

Code: Select all

 CREATE TABLE F0001 (
`SHOP_ID`                          Integer, 
`KAP_NR`                           Integer, 
`KORT_NR`                          Integer, 
`BEDRAGK`                          Numeric(6,2), 
`UUR`                              Integer, 
`REC_DATE`                         Date, 
`VERKOOP`                          Numeric(7,2), 
`EX_VERK`                          Numeric(7,2), 
`TOTAL`                            Numeric(11,2));
The DBF file is attachted!

Serge
Attachments
F0001.rar
(328.33 KiB) Downloaded 263 times
There's nothing you can do that can't be done...
User avatar
serge_girard
Posts: 3158
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: MySql revisited

Post by serge_girard »

And PERSONEL.SQL attached!
Attachments
PERSONEL.rar
(8.63 KiB) Downloaded 265 times
There's nothing you can do that can't be done...
User avatar
BeGeS
Posts: 125
Joined: Fri Jul 14, 2017 10:45 am
DBs Used: DBF
Location: La Mancha, Spain

Re: MySql revisited

Post by BeGeS »

serge_girard wrote: Wed Aug 09, 2017 5:22 pm Hello,

I made a little demo which shows the difference between working with DBF-files and MySQl.
Not so fast, Serge... First I have to know the graphical interface well, and then I will expand my knowledge with SQL. I really want to, but everything in due time.

I am sure that I will weary you and other colleagues with my questions. :lol: :lol:

* * * * * * * * *

"// hier fout" :roll: :shock: :?

U herinner me mijn eerste groet?
Franse naam, Vlaamse stad... 50% kans op fout.
En het begon werkend Murphy Act.
Vergeef me. :oops:
I get by with a little help from my friends
User avatar
BeGeS
Posts: 125
Joined: Fri Jul 14, 2017 10:45 am
DBs Used: DBF
Location: La Mancha, Spain

Re: MySql revisited

Post by BeGeS »

Serge, I have no doubts about the superiority of SQL over DBF, but I do not see three WHILE structures necessary either.
On the other hand, I think this piece of code only leads to print the first line and it's over:

Code: Select all

DO WHILE .NOT. EOF()
   nSHOP_ID := F0001->SHOP_ID

   DO WHILE .NOT. EOF() .AND.  nSHOP_ID == F0001->SHOP_ID
      dREC_DATE   := F0001->REC_DATE
      nTOTAL      := 0.00

      DO WHILE .NOT. EOF() .AND.  nSHOP_ID == F0001->SHOP_ID .AND. dREC_DATE == F0001->REC_DATE
         nTOTAL   := nTOTAL   + F0001->TOTAL   
         SKIP
      ENDDO
      ? nSHOP_ID, dREC_DATE, nTOTAL
   ENDDO
ENDDO
I would do so, with a WHILE. It consists of reading until the next change of reference or date and then print the line:

Code: Select all

LOCAL cRESERVA,nVARIA1,dVARIA2
 ...

WHILE .NOT. EOF()
   nSHOP_ID := F0001->SHOP_ID
   dREC_DATE:= F0001->REC_DATE

   IF cRESERVA=="" ; cRESERVA:= STR(nSHOP_ID,2)+DTOS(dREC_DATE) ; nTOTAL:= 0 ; ENDIF

   IF cRESERVA<>STR(nSHOP_ID,2)+DTOS(dREC_DATE)
     nVARIA1:=VAL( LEFT(cRESERVA,2) )
     dVARIA2:=CTOD( SUBSTR(cRESERVA,9,2)+"/"+SUBSTR(cRESERVA,7,2)+"/"+SUBSTR(cRESERVA,3,4) ) 
     ? nVARIA1, dVARIA2, nTOTAL

     cRESERVA:= STR(nSHOP_ID,2)+DTOS(dREC_DATE) ; nTOTAL:= 0 
   ENDIF

   nTOTAL:= nTOTAL + F0001->TOTAL   
   SKIP
END

   IF cRESERVA<>""                            // cRESERVA has the latest data  
     nVARIA1:=VAL( LEFT(cRESERVA,2) )
     dVARIA2:=CTOD( SUBSTR(cRESERVA,9,2)+"/"+SUBSTR(cRESERVA,7,2)+"/"+SUBSTR(cRESERVA,3,4) ) 
     ? nVARIA1, dVARIA2, nTOTAL
   ENDIF
I get by with a little help from my friends
User avatar
dragancesu
Posts: 920
Joined: Mon Jun 24, 2013 11:53 am
DBs Used: DBF, MySQL, Oracle
Location: Subotica, Serbia

Re: MySql revisited

Post by dragancesu »

BeGeS, I think I know how you feel, but for comfort, everyone has gone through it, try it

viewtopic.php?f=10&t=4170

Clippers and hmg, similar but not the same, hmg program is a clipper program but without the command SAY and GET, you will have to get used to it
Post Reply