if i have form, and there are two field A, b which is flowfield type, then I want this form only show A>B , and fix filter, don’t let user show all record. how to do it with high speed performance? since in the form, we have so many record, I must think about solution has high speed.
Hi, Usually in such situations you can MARK suitable records and show marked only records. But it would not be good performance, because you have to go through all records and calculate flowfields for all of them. And also you can not fix “marked only” filter. If you need good performance, you should have one normal (not flowfield) field, by which you can decide to show record or not. Viktoras
Filtering comparing fields of the same record must always be a sequential solution, therefore it’ll always be a slow solutions. You’ll have to figure out something that prepares the result of this comparison in a field (normal or a new flowfield) that allows to apply a direct filter. Saludos Nils
You might be able to get away with speed if your form is keyed by A. You can use FILTERGROUP to not allow the user to change the fixed filter. You can use SETFILTER(A,’<%1’,GETFILTER(B)) to filter the records. The GETFILTER might have to be changed depending the values in the FlowFilter (Can it be a range), but this should point you in the right direction.
I found upper solution can’t meet my requirement, is there anyone can help me solve it?
The only way I can think of, is a bit rough, and if you have many records may be to slow, but let us know; Add a new physical field type Boolean,and a Key, make the field non editable. Then create a codeunit. Run through the records an set the Boolean Add a Variable ValueIsGreater type Boolean MyRec.RESET; Window.OPEN(‘Processing Please wait #1#############’); REPEAT Window.UPDATE(1,MyRec.MyKey); MyRec.CALCFIELDS(A,B); ValueIsGreater := MyRec.MyBoolean; MyRec.MyBoolean:=MyRec.A>MyRec.B; // We Only Need to change the Boolean, modify the record, if Different //to last saved version, this should save on COMMIT Times. IF ValueIsGreater <> MyRec.MyBoolean THEN MyRec.MODIFY; UNTIL MyRec.NEXT=0; Window.CLOSE; COMMIT; SELECTLATESTVERSION; MyRec.SETCURRENTKEY(MyBoolean); MyRec.SETRANGE(MyBoolean,TRUE); FORM.RUN(MyForm,MyRec); give the user a link to the codeunit. hope this helps P.S. Remember to set permissions for the codeunit to modify the table.
William, you reall have three options. @ mentioned above. 1/ Use Marks. These are very problematic, and cna be very slow if the primary key is not seleted. Also the calculation only lasts whilst the currnet form is open. In Navision Marks are normally only used when we have already filtersed the recored set down to a small sub set of records, and need to fine tune the last few. Eg I may filter Itme Ledger Item number and Location, and now have a small enough sub set to use Marks on. Keep in mind that marks are stored locally on the client, and are stored sorted by primary key. 2/ Use Davids solution above to create a permanant filterable field. This solution works well when the conditions do not change too much. And you could just runt he update routine once a day or once a week. If the data cahnges every few minutes, then the Marks solution may be easier. 3/ Redesign the data. In most cases where this requirement happens, there are other possibilities to resolve the issue that cna work much better. If you can explain what you are trying to do, then maybe you will get some good solutions that may involve changing the structre a little.
Hello, I had a similar problem with the G/L Account list which should only show accounts which have postings in a defined period or are preselected as “show always”. After (more than) a bit of tinkering I came up with the following solution. To filter the records dynamically I used the OnFindRecord and OnNextRecord triggers of the form to select the next record which fits the requirements. Due to the nature of these triggers you have to calculate the flowfields for almost every record that you skip. The performance is better than I expected, it more or less “feels” like a normal list window. Form 16, triggers: Form - OnOpenForm()
SETRANGE("Date Filter",0D,WORKDATE); L_AccPeriod1.SETCURRENTKEY("Show in Account List"); L_AccPeriod1.SETRANGE("Show in Account List",TRUE); IF L_AccPeriod1.FIND('-') THEN BEGIN ShowStartDate:=L_AccPeriod1."Starting Date"; L_AccPeriod1.FIND('+'); L_AccPeriod2.GET(L_AccPeriod1."Starting Date"); IF L_AccPeriod2.NEXT=0 THEN BEGIN SETRANGE("Has Entries Date Filter",ShowStartDate,31129999D); END ELSE BEGIN SETRANGE("Has Entries Date Filter",ShowStartDate,L_AccPeriod2."Starting Date"-1); END; END; ShowWithEntries:=TRUE; Form - OnFindRecord(Which : Text) : Boolean
IF ShowWithEntries THEN BEGIN L_found:=FIND(Which); CALCFIELDS("Has Entries"); "Has Entries":=("Has Entries" OR "Show Always") AND (NOT Blocked); L_found:="Has Entries"; IF NOT L_found THEN BEGIN CASE Which OF '-': BEGIN L_found:=NextRec(Rec,1)=1; END; '+': BEGIN L_found:=NextRec(Rec,-1)=-1; END; '=><': BEGIN L_found:=NextRec(Rec,1)<>0; IF NOT L_found THEN BEGIN L_found:=NextRec(Rec,-1)<>0; END; END; END; END; EXIT(L_found); END ELSE EXIT(FIND(Which)); Form - OnNextRecord(Steps : Integer) : Integer
IF ShowWithEntries THEN BEGIN EXIT(NextRec(Rec,Steps)); END ELSE EXIT(NEXT(Steps)); Functions: NextRec(VAR L_Rec : Record “G/L Account”;L_Steps : Integer) : Integer
L_Rec2.COPY(L_Rec); REPEAT L_DeltaSteps:=NextRecSingleStep(L_Rec2,sgn(L_Steps)); L_TempSteps+=L_DeltaSteps; UNTIL (L_DeltaSteps=0) OR (L_TempSteps=L_Steps); IF L_TempSteps<>0 THEN BEGIN //Clipping: upper or lower border have been reached bevor all steps were executed. L_Rec2 contains the first/last //record, which is not necessarily within the filters. L_Rec2 wil be checked again, and if not valid we go one step backwards. IF L_TempSteps<>L_Steps THEN BEGIN L_Rec2.CALCFIELDS("Has Entries"); L_Rec2."Has Entries":=(L_Rec2."Has Entries" OR L_Rec2."Show Always") AND (NOT L_Rec2.Blocked); IF NOT L_Rec2."Has Entries" THEN BEGIN IF NextRecSingleStep(L_Rec2,-sgn(L_Steps))<>-sgn(L_Steps) THEN EXIT(0); END; END; L_Rec.COPY(L_Rec2); EXIT(L_TempSteps); END ELSE EXIT(0); sgn(Wert : Integer) : Integer
IF Wert<>0 THEN EXIT(ROUND(Wert/ABS(Wert),1)) ELSE EXIT(0); NextRecSingleStep(VAR L_Rec : Record “G/L Account”;L_Steps : Integer) : Integer
WITH L_Rec DO BEGIN L_TempSteps:=NEXT(L_Steps); IF L_TempSteps<>L_Steps THEN BEGIN EXIT(0); END ELSE BEGIN CALCFIELDS("Has Entries"); "Has Entries":=("Has Entries" OR "Show Always") AND (NOT Blocked); IF NOT "Has Entries" THEN BEGIN REPEAT L_TempSteps:=NEXT(L_Steps); IF L_TempSteps<>0 THEN BEGIN CALCFIELDS("Has Entries"); "Has Entries":=("Has Entries" OR "Show Always") AND (NOT Blocked); END ELSE EXIT(0); UNTIL "Has Entries"; EXIT(L_Steps); END ELSE EXIT(L_Steps); END; END; with best regards Jens Glathe