QM.Sort.Item
From Pickwiki
Jump to navigationJump to search
Back to BasicSource
This program allows you to change the sort order of all the data in associated multivalued attributes. You can have one or more of the attributes as keys and have different sorting criteria for each. One or more attributes can be data and are kept in synch with the key data.
SUBROUTINE QM.SORT.ITEM(ITEM,KEYS,DATA,PROBLEM) * Copyright 2013 Keith Johnson - You can use this program however you want * ITEM - is a Pick record comtaining associated multivalues * KEYS - is a set of attributes * value 1 is the attribute in the record * value 2 is the sort number * 0 left justified * 1 right justified * 2 compound * 3 right justified for numbers * +16 if descending * +64 if not case sensitive * DATA - is a set of attributes for the associated multivalues * * This program uses the QM functions SORT and SORTNEXT * and statements SORTADD and SORTCLEAR * so it ain't gonna work on yer standard Pick! * * An honest and earnest "thank you" to Martin Phillips. * * The idea is that a record contains a number of associated multivalues - * some of these are keys, and others data. We wish to re-arrange the * multivalues in a different order without disrupting the associations. * * There are speed advantages to using attributes rather than values, * hence there are CONVERT lines that would be otherwise puzzling. KATS = DCOUNT(KEYS,@AM) IF KATS LT 1 THEN RETURN PROBLEM = '' OK = '0\1\2\3\16\17\18\19\64\65\66\67\80\81\82\83' CONVERT '\' TO @AM IN OK * Checking the information DIM LOCK(KATS) DIM TYPE(KATS) DIM THAT(KATS) MAXM = 0 USED = '' FOR KATR = 1 TO KATS ANUM = KEYS<KATR,1> IF NOT(ANUM MATCHES '1[[N0N]]') THEN PROBLEM = 'NON-NUMERIC KEY ATTRIBUTE' ; GO AWAY IF ANUM LT 1 THEN PROBLEM = 'KEY ATTRIBUTE ':ANUM:' LESS THAN 1' ; GO AWAY IF MAXM LT ANUM THEN MAXM = ANUM SNUM = KEYS<KATR,2> IF NOT(SNUM MATCHES '1[[N0N]]') AND SNUM NE '' THEN PROBLEM = 'NON-NUMERIC KEY SORT' ; GO AWAY SNUM += 0 IF SNUM GT 128 THEN SNUM -= 128 ;* we'll see... LOCATE(SNUM,OK;POSN) ELSE PROBLEM = 'INVALID KEY SORT ':SNUM ; GO AWAY LOCK(KATR) = SNUM TYPE(KATR) = ANUM LOCATE(ANUM,USED;POSN;'AR') THEN PROBLEM = 'KEY ATTRIBUTE ':ANUM:' ALREADY USED' GO AWAY END ELSE INS ANUM BEFORE USED<POSN> NEXT KATR DATS = DCOUNT(DATA,@AM) DIM WHAT(DATS) FOR DATR = 1 TO DATS DNUM = DATA<DATR> IF NOT(DNUM MATCHES '1[[N0N]]') THEN PROBLEM = 'NON-NUMERIC DATA ATTRIBUTE' ; GO AWAY IF DNUM LT 1 THEN PROBLEM = 'DATA ATTRIBUTE ':ANUM:' LESS THAN 1' ; GO AWAY WHAT(DATR) = DNUM IF DNUM GT MAXM THEN MAXM = DNUM LOCATE(DNUM,USED;POSN;'AR') THEN PROBLEM = 'DATA ATTRIBUTE ALREADY USED' GO AWAY END ELSE INS DNUM BEFORE USED<POSN> NEXT DATR * Parse DIM ARRAY(MAXM+1) MATPARSE ARRAY FROM ITEM * Change values to attributes and get size LONG = 0 SOME = @FALSE FOR KATR = 1 TO KATS CONVERT @VM TO @AM IN ARRAY(TYPE(KATR)) CNTR = DCOUNT(ARRAY(TYPE(KATR)),@AM) IF CNTR GT LONG THEN LONG = CNTR NEXT KATR FOR DATR = 1 TO DATS CONVERT @VM TO @AM IN ARRAY(WHAT(DATR)) CNTR = DCOUNT(ARRAY(WHAT(DATR)),@AM) IF CNTR GT LONG THEN LONG = CNTR IF CNTR THEN SOME = @TRUE NEXT DATR IF SOME THEN LOCK(1) += 128 ;* there IS data to be retained SORTVAR = SORT(KATS, MAT LOCK) *Stash the data in the sort variable FOR XX = 1 TO LONG MAT THAT = '' FOR KATR = 1 TO KATS THAT(KATR) = ARRAY(TYPE(KATR))<XX> NEXT KATR THIS = '' FOR DATR = 1 TO DATS THIS<DATR> = ARRAY(WHAT(DATR))<XX> NEXT DATR CONVERT @AM TO @VM IN THIS SORTADD SORTVAR, MAT THAT, THIS NEXT XX * Clear the data areas FOR KATR = 1 TO KATS ARRAY(TYPE(KATR)) = '' NEXT KATR FOR DATR = 1 TO DATS ARRAY(WHAT(DATR)) = '' NEXT DATR * Retrieve the sorted data CNTR = 0 LOOP THIS = SORTNEXT(SORTVAR, MAT THAT) UNTIL STATUS() CNTR += 1 FOR KATR = 1 TO KATS ARRAY(TYPE(KATR))<CNTR> = THAT(KATR) NEXT KATR CONVERT @VM TO @AM IN THIS FOR DATR = 1 TO DATS ARRAY(WHAT(DATR))<CNTR> = THIS<DATR> NEXT DATR REPEAT * Change all the fields to values FOR KATR = 1 TO KATS CONVERT @AM TO @VM IN ARRAY(TYPE(KATR)) NEXT KATR FOR DATR = 1 TO DATS CONVERT @AM TO @VM IN ARRAY(WHAT(DATR)) NEXT DATR * Tidy up MATBUILD ITEM FROM ARRAY SORTCLEAR SORTVAR MAT ARRAY = '' AWAY: RETURN