macro substitution & in fieldnames

Post Reply
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

macro substitution & in fieldnames

Post 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

             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

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
Marc Venken
Using: FWH 20.08 with Harbour
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: macro substitution & in fieldnames

Post by cnavarro »

Look, I hope it's what you need

Code: Select all


#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

 
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
User avatar
dutch
Posts: 1395
Joined: Fri Oct 07, 2005 5:56 pm
Location: Thailand

Re: macro substitution & in fieldnames

Post by dutch »

Dear Marc,

I use as you did but a bit different.

Code: Select all

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

FWH 19.01 / xHarbour Simplex 1.2.3 / BCC73 / Pelles C / UEStudio
FWPPC 10.02 / Harbour for PPC (FTDN)
ADS V.9 / MySql / MariaDB
R&R 12 Infinity / Crystal Report XI R2
(Thailand)
hmpaquito
Posts: 1200
Joined: Thu Oct 30, 2008 2:37 pm

Re: macro substitution & in fieldnames

Post 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

// 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
puenteda
Posts: 19
Joined: Thu Oct 02, 2014 3:51 am

Re: macro substitution & in fieldnames

Post 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
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: macro substitution & in fieldnames

Post 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


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


 
Marc Venken
Using: FWH 20.08 with Harbour
hmpaquito
Posts: 1200
Joined: Thu Oct 30, 2008 2:37 pm

Re: macro substitution & in fieldnames

Post by hmpaquito »

Here you are:

Code: Select all


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


 
User avatar
Marc Venken
Posts: 727
Joined: Tue Jun 14, 2016 7:51 am

Re: macro substitution & in fieldnames

Post by Marc Venken »

Thanks,

It works! and is better for reading the code.

Learning every day..

Thanks.
Marc Venken
Using: FWH 20.08 with Harbour
Post Reply