Merge TPS files

Hi All,
I have 2 .TPS files and i want merge them! so is there and app that do this? or how can i i do that?
Thank you

Iā€™ve always used the dct ā€˜create a conversion programā€™ to create source and go from there.

im new so can you send me the project or share the source code here! Thank you

assuming that both files have the same fields.

program

PROGRAM

MAP
END

file1 FILE,DRIVER(ā€˜TOPSPEEDā€™),NAME(ā€˜file1.tpsā€™),pre(f1)
record record
field1 long
! ect
end
end

file2 FILE,DRIVER(ā€˜TOPSPEEDā€™),NAME(ā€˜file2.tpsā€™),PRE(F2)
record record
field1 long
end
end

code
    open(file1)
    if  errorcode()
        message('can not open file1')
        return                               
    end 
    OPEN(FILE2)
    if  errorcode()
        message('can not open file2')
        return                     
    end 
    ! READ FILE 1 AND ADD TO FILE2
    SET(FILE1)
    LOOP
        NEXT(FILE1)
        IF ERRORCODE()
            BREAK
        END
        
        FILE2.record = FILE1.record
        ADD(FILE2)
    END
    CLOSE(file1)
    CLOSE(file2)

Are the files of the same structure? I have had good results in the past using the Topspeed ODBC driver and doing it all within Access or some other front end tool to write and test the INSERT queries.

I believe you used to be able to get an evaluation copy of the ODBC drivers in the past, which gives you enough time to run a conversion? Not sure if you still can now though.

We use this in some parts of our app, itā€™s similar like this but includes more tps files at once. Is there any possibilty(maybe there is something already made) to create a program which will take a random tps file which is picked by the user and merge it with another one(assume we are always merging files with identical fields). This would be something universal where we donā€™t need to know the exact structure of the tps files we are working with. The example you gave is more static, and the tps files need to be defined in start. Hope my explanation makes sense.

I would say using ā€œstandardā€ Clarion there is no way you could do this. Clarion is very reliant on file buffers: a record is read off the disk into a file buffer, a file buffer is written back to the disk. Even if you are using the :=: operator to copy an entire record, Clarion needs to have reserved space for the file buffer. You may be able to do what you want using the Dynamic File Driver add-on, which I think will create a file buffer at run-time.

Seems like it could be done with 1 FILE by saving the Records into a Queue.

  1. Set FILE Name to the ā€œFrom Fileā€ name and Open it
  2. SET() ; LOOP ; NEXT() and add all the records to a Queue
  3. Close the ā€œFrom Fileā€
  4. Set FILE Name to the ā€œTo Fileā€ name and Open it
  5. Loop the Queue and Add to the File

You have PROP:Record to get a &GROUP reference to the Record of any &FILE reference. If you wanted to move Memoā€™s there are PROPā€™s for those too.

The QUEUE would need to hold a Record of any size so itā€™s field could be an ANY or &STRING. Instead you could write it to a DOS file if you were concerned about memory limits.

1 Like

perhaps writing out to JSON or XML then reading that back in?

perhaps the hardest part is ā€œto create a program which will take a random tps fileā€ as you need to be able to open and read this file without knowing the structure in advance. There used to be a library that did that - see

for info on my attempt to buy DynaLib many years back. There is plenty of information about the structure of a tps file so it should be possible to ā€œroll your ownā€ but perhaps more work than the OP wants to do:

hth

Geoff

I would deal only with the RECORD so no need to know fields. Maybe like this:

MergeFiles procedure(*file FileRef, STRING FromFileName, STRING MergeToFileName)
FileRef:Record &group, auto
RecordsQ    QUEUE,Pre(RecsQ)
TheRecord       ANY
            END 
Ndx LONG,AUTO             
OriginalFileName    STRING(260)            
  code
  FileRef:Record &= FileRef{PROP:Record}
  OriginalFileName = FileRef{PROP:Name}
  DO LoadRecordsRtn
  IF RECORDS(RecordsQ) THEN 
     DO MergeRecordsRtn
     DO FreeQRtn 
  END 
  FileRef{PROP:Name} = OriginalFileName
  RETURN 

LoadRecordsRtn ROUTINE
    CLOSE(FileRef)
    FileRef{PROP:Name} = FromFileName
    SHARE(FileRef)
    !Error checking 
    SET(FileRef)
    LOOP 
        NEXT(FileRef) ; IF ErrorCode() THEN BREAK.
        CLEAR(RecordsQ)     !Queue with ANY Must Clear() or GPF 
        RecsQ:TheRecord = FileRef:Record
        ADD(RecordsQ)
    END
    CLOSE(FileRef)
    EXIT 

MergeRecordsRtn ROUTINE
    CLOSE(FileRef)
    FileRef{PROP:Name} = MergeToFileName
    SHARE(FileRef)
    !Error checking 
    LOOP Ndx=1 TO RECORDS(RecordsQ)
        GET(RecordsQ,Ndx) 
        CLEAR(RecordsQ)     !Queue with ANY Must Clear() or GPF 
        FileRef:Record = RecsQ:TheRecord
        ADD(FileRef)
        !Error checking
    END
    CLOSE(FileRef)
    EXIT 

FreeQRtn ROUTINE    
    LOOP Ndx=1 TO RECORDS(RecordsQ)
        GET(RecordsQ,Ndx) 
        CLEAR(RecordsQ)  !Not sure this is right, see help on ANY 
    END 
    FREE(RecordsQ)       !Not sure this is right, see help on ANY 
    EXIT 

Called like this

COPY(CustomerFile,  'C:\Temp\CustomersMerged.TPS')  !Put current file in Temp
MergeFiles(CustomerFile, 'C:\Temp\Customers2Import.TPS', 'C:\Temp\CustomersMerged.TPS')
1 Like