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.
- Set FILE Name to the “From File” name and Open it
- SET() ; LOOP ; NEXT() and add all the records to a Queue
- Close the “From File”
- Set FILE Name to the “To File” name and Open it
- 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.
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')