Page 1 of 1

macro substitution & in fieldnames

PostPosted: Tue Oct 25, 2016 9:16 pm
by Marc Venken
It is a piece of code for a mapping system

I have 3 databases

dbf1 -> with just 1 record filled with fieldnames of dbf 2
ID : "STYLE"
NAME : "TITLE"
CATMAIN : "CAT1"
...

dbf2 -> actual datafile (source data)
STYLE : "200444"
TITLE : "Safetyshoes dassy"
CAT1 : "Safetyshoes"
....

dbf3 -> target datafile where i what to put the data from dbf2
ID : "CUST->STYLE" -> should be "200444"
NAME : "CUST->TITLE" -> should be 'Safetyshoes dassy"
CATMAIN : "CUST->CAT1" ->should be 'Safetyshoes"

So, I do something wrong with the & operator

Here I miss the logic of converting strings
Code: Select all  Expand view

             if apos > 0  // if >0, it is a fieldname else a standard data like "21%"
                cTarget = "slave->"+fieldname(i)

  //            cField = "CUST->"+aCustfields[i]
                cField = "CUST->"+cLookup

 //               cData = &cField // not working
                cData = cField

              &cTarget = cData
            else  // standard data, but no fieldname
                cData = cField  
                &cTarget = cData
           endif

 



Full Function

Code: Select all  Expand view

function filldbf()
   Local aCustfields:={}

   use slave
   select slave
   zap
   close
   use DASSY NEW alias CUST
   use slave NEW alias slave
   use master NEW alias master

   select cust
   for i = 1 to cust->(FCOUNT())
      AADD(aCustfields,Fieldname(i))  // make arry with all fieldnames from datafile
   next

   select master
   master->(dbgotop())
   nMasterfields = master->(fcount())
   cust->(dbgotop())
   nTel = 0

   do while !cust->(eof())
      slave->(dbappend())

      for i = 1 to nMasterfields

         cWelkField = "master->"+fieldname(i)
         clookup = alltrim(&cWelkfield)        // data from the masterfile, result = fieldname to look for next
         if !empty(clookup)
            apos = ascan(aCustfields,clookup)  // to see if the data is a fieldname, could also be simple data

             if apos > 0  // found as a fieldname
                cTarget = "slave->"+fieldname(i)

  //            cField = "CUST->"+aCustfields[i]
                cField = "CUST->"+cLookup

 //               cData = &cField // not working
                cData = cField

              &cTarget = cData
            else  // standard data, but no fieldname
                cData = cField  // GIVES THE DATA, BUT ERROR FOR THE NEXT DO/ENDDO LOOK
                &cTarget = cData
           endif
         endif
        next
      cust->(dbskip())
   enddo

   select slave
   xbrowse()
   close all
return
 


The result is a database filled with the fieldnames, but not the fielddata

Image

Re: macro substitution & in fieldnames

PostPosted: Wed Oct 26, 2016 12:13 am
by cnavarro
Look, I hope it's what you need

Code: Select all  Expand view


#include "Fivewin.ch"

MEMVAR cAlias

//----------------------------------------------------------------------------//

Function Main()

   //local cAlias
   local cField
   local uVal
   
Use "Customer.dbf" ALIAS custom
   
   cAlias := Alias()
   
   cField := ( cAlias )->( FieldName( 1 ) )
   ? ( cAlias )->( FieldName( 1 ) ), ( cAlias )->( FieldGet( 1 ) )
   uVal := ( cAlias )->First
   ? uVal, cField
   cField := "( cAlias )->"+cField
   ? &(cField)
   &(cField)  := "Field modified"
   //   &(cField)  := "Homer"
   ? ( cAlias )->( FieldGet( 1 ) )

Return nil

 

Re: macro substitution & in fieldnames

PostPosted: Wed Oct 26, 2016 7:57 am
by dutch
Dear Marc,

I use as you did but a bit different.
Code: Select all  Expand view

RvName := 'MHS->MHS_RV'+right(dtos(MEMVAR->comdat),2)
&(RvName) += round(TRN->TRN_UNIT * TRN->TRN_QTTY,2)
 

Re: macro substitution & in fieldnames

PostPosted: Wed Oct 26, 2016 8:42 am
by hmpaquito
Macro substitution is bad:
- slow (more slow than dbf field functions)
- avoid compiler syntax analisys.


Better harbour programming style is do not use macro substitution, so:

Code: Select all  Expand view
// With preprocessor  is more rapid and clear with pseudo functions:
#Define FPOS_(aTarget) ;
            (aTarget[1])-> ( FieldPos(aTarget[2]) )
#Define FPUT(aTarget, xValue) ;
            (aTarget[1])-> ( FieldPut( FPOS_(aTarget), xValue) )
#Define FGET_(aTarget) ;
            (aTarget[1])-> ( FieldGet( FPOS_(aTarget), xValue) )

// Sample:
aTarget:= {"slave", fieldname(1)}

FPUT_(aTarget, "hi !")
xVar:= FGET_(aTarget)
nPos:= FPOS_(aTarget)


Regards

Re: macro substitution & in fieldnames

PostPosted: Wed Oct 26, 2016 3:19 pm
by puenteda
Marc:

Look at this examples code:

PADRON->(DBGOTOP())
DO WHILE !PADRON->(EOF())

IF !TMOVMES->(DBSEEK(CONCEPTO->COD+PADRON->MP,.F.))

TPADRON->(DBAPPEND())
COPIAREG('TPADRON','PADRON')

ENDIF

PADRON->(DBSKIP())
ENDDO

FUNCTION COPIAREG(xBaseEntra,xBaseSale)

Local aCampos:={},i,aDatos:={},aCampos2,aAt

aCampos:=(xBaseEntra)->(dbstruct())
aCampos2:=(xBaseSale)->(dbstruct())

FOR I:=1 TO LEN(aCampos2)
IF ASCAN(aCampos,{|aAt| aAt[1]==aCampos2[i,1]}) >0
(xBaseEntra)->&(aCampos2[i,1]):=( xBaseSale )->&(aCampos2[i,1])
ELSE
* ? 'NO EXISTE EL CAMPO EN ',XBASEENTRA,'I=',I,aCampos2[i,1]
ENDIF
NEXT

return nil


BUS_DES('PADRON',2,MOVMES->MP,'ESPE')

Function BUS_DES(XARCH, XORDEN, XCLAVE, XCAMPO)

Local RET:=SPAC(0) , ORD_ACT, AREA_ACT := SELECT(), cRegis

IF SELECT(XARCH) == 0
USE (WPATH + "\" + XARCH) SHARED NEW
ENDIF

DBSELECTAR(XARCH)
cRegis:=RECNO()
ORD_ACT = INDEXORD()

SET ORDER TO XORDEN

DBSEEK((XCLAVE))
IF FOUND() .AND. !DELETED()
RET = EVAL(FIELDBLOCK(XCAMPO))
ELSE
DBGOBOTTOM()
RET = SPACE(LEN(EVAL(FIELDBLOCK(XCAMPO))))
ENDIF
SET ORDER TO ORD_ACT
DBGOTO(cRegis)
SELECT(AREA_ACT)

RETURN RET


Regards,
Daniel Puente

Re: macro substitution & in fieldnames

PostPosted: Wed Oct 26, 2016 11:37 pm
by Marc Venken
Thanks guys,

With the samples I get it to work !

hmpaquito wrote:Macro substitution is bad:
- slow (more slow than dbf field functions)
- avoid compiler syntax analisys.

Better harbour programming style is do not use macro substitution:


Out of curiosity, You suggested code from Harbour Style.
I'm just new with the FW programming and my skilss are not ready for it yet,
but I wonder how your working code would look like. Here is the code that works for me now.
Should you have any time, i would be a great learning stuff for me.

Code: Select all  Expand view


function filldbf()
   Local aCustfields:={}
   local cField
   local uVal
   local cM_field

   MEMVAR cAlias

   use slave
   select slave
   zap
   close
   use DASSY NEW alias CUST
   use slave NEW alias slave
   use master NEW alias master

   select cust
   AliasCust = alias()
   select slave
   Aliasslave = alias()
   select master
   Aliasmaster = alias()

   select cust
   for i = 1 to cust->(FCOUNT())
      AADD(aCustfields,Fieldname(i))  // make arry with all fieldnames from datafile
   next

   select master
   master->(dbgotop())
   nMasterfields = master->(fcount())

   master->(dbgotop())
   cust->(dbgotop())
   do while !cust->(eof())
      slave->(dbappend())
      for i = 1 to nMasterfields
         cM_Field := alltrim(( Aliasmaster )->(FieldGet(i)))
         if !empty(cM_Field)
             nPos = ascan(aCustfields,cM_Field)  // to see if the data is a fieldname, could also be simple data
             cSlaveField := "slave->"+(aliasslave)->(fieldname(i))
             if nPos > 0  // found as a fieldname
                &(cSlavefield) := cust->(fieldget(nPos))
             else  // standard data, but no fieldname
                &(cSlavefield) := &(AliasMaster)->(fieldget(I))
             endif
         endif
        next
      cust->(dbskip())
   enddo
   select slave
   xbrowse()
   close all
return


 

Re: macro substitution & in fieldnames

PostPosted: Thu Oct 27, 2016 7:24 am
by hmpaquito
Here you are:

Code: Select all  Expand view


function filldbf()
   Local aCustfields:={}
   local cField
   local uVal
   local cM_field

   // MEMVAR cAlias

   use slave
   select slave
   zap
   close
   use DASSY NEW alias CUST
   use slave NEW alias slave
   use master NEW alias master

   select cust
   AliasCust = alias()
   select slave
   Aliasslave = alias()
   select master
   Aliasmaster = alias()

   select cust
   for i = 1 to cust->(FCOUNT())
      AADD(aCustfields,Fieldname(i))  // make arry with all fieldnames from datafile
   next

   select master
   master->(dbgotop())
   nMasterfields = master->(fcount())

   master->(dbgotop())
   cust->(dbgotop())
   do while !cust->(eof())
      slave->(dbappend())
      for i = 1 to nMasterfields
         cM_Field := alltrim(( Aliasmaster )->(FieldGet(i)))
         if !empty(cM_Field)
             nPos = ascan(aCustfields,cM_Field)  // to see if the data is a fieldname, could also be simple data
             cSlaveField := "slave->"+(aliasslave)->(fieldname(i))
             if nPos > 0  // found as a fieldname
                // &(cSlavefield) := cust->(fieldget(nPos))
                Slave-> ( FieldPut ( i,  Cust->(FieldGet(nPos)) )  // This and...
             else  // standard data, but no fieldname
                // &(cSlavefield) := &(AliasMaster)->(fieldget(I))
                Slave-> ( FieldPut ( i,  (cAliasMaster)->(FieldGet(i)) )  // ... this
             endif
         endif
        next
      cust->(dbskip())
   enddo
   select slave
   xbrowse()
   close all
return


 

Re: macro substitution & in fieldnames

PostPosted: Thu Oct 27, 2016 10:26 pm
by Marc Venken
Thanks,

It works! and is better for reading the code.

Learning every day..

Thanks.