wir nutzen viele Ansichten in Kombination mit Suchfeldern, nun hatte ich mir vorgenommen, dass es nur noch ein Textfeld sein soll, welches als Suchfeld fungiert. Aber halt erweiterte Suche möglich sein sollte mit Operatoren und Klammern. Dies hatte ich jetzt soweit umgesetzt bekommen.
Die Suchfunktion unterstützt folgende Operatoren:
+ (UND): Kombiniert zwei Suchbegriffe, beide müssen vorkommen
/ (ODER): Findet Einträge, die mindestens einen der Suchbegriffe enthalten
- (AUSSER): Schließt Einträge aus, die einen bestimmten Begriff enthalten
Dachte wäre eventuell auch für andere Nutzer interessant, daher habe ich eine Beispiel Datenbank angehängt.
Anpassung für eigene Datenbanken
Die Lösung lässt sich an eure eigenen Tabellen und Felder anpassen:
Ändert projekt : 'Filterung Ansicht' auf eure Tabelle
Passt projekt.Material auf eure Relation an
Passt die Suchfelder an (Hersteller, Oberbegriff, Herstellernummer)
und es würde mich interessieren, ob es dafür eine bessere Lösung geben würde, als den Weg den ich genommen habe.
5Antworten
mirko3
vor 9 Tagen
Gemeldet - anzeigen
Hi , tolle (und viel) Arbeit. Das alles in einzelne Funktionen unterzubringen ist eine kluge Idee bei längerem Code, um ihn übersichtlicher zu machen. Scheint auch alles perfekt zu funktionieren. Danke. Mirko
Josef_Koenig
vor 9 Tagen
Gemeldet - anzeigen
Sehr schönes Projekt! Vielen Dank!
Ich habe folgendes ausprobiert: Eingabe: test - siemens
Das erwartete Ergebnis wären - wie auch Deine TextInfo-Box anzeigt - die Datensätze 2, 4, 5, 6 Angezeigt werden aber die Datensätze 1 und 3 (so als hätte man nicht - (AUSSER), sondern + (UND) eingetippt.
Lamping & Reisig Gmbh & Co.KG
LuRLorenz
vor 8 Tagen
Gemeldet - anzeigen
das stimmt, hatte nicht alle Fälle ganz betrachtet. Konnte den Code jetzt aber noch etwas kürzen und sollte jetzt auch noch etwas effizienter sein und dazu richtig.
Das hier ist jetzt der Code aus dem Button, für die Ansicht die Zeile 164 entfernen.
function getMaterialOverNr(projekt : 'Filterung Ansicht',filterNr : text) do
let textNrs := split(filterNr, ", ");
let numbersNrs := [0];
for x in textNrs do
if x != "" then
numbersNrs := array(numbersNrs, [number(x)])
end
end;
projekt.'Alle Vorhandenen Materialien'[contains(numbersNrs, number(this.Nr))]
end;
function filterMaterial(projekt : 'Filterung Ansicht',suchText : text,filterTextNrs : text) do
if suchText = "x§x" then
getMaterialOverNr(projekt, filterTextNrs)
else
projekt.'Alle Vorhandenen Materialien'[Hersteller like suchText or Oberbegriff like suchText or
Herstellernummer like suchText]
end
end;
function getProjektMaterial(projekt : 'Filterung Ansicht',suchText : text,filterTextNrs : text) do
let ziel := projekt.'Alle Vorhandenen Materialien';
if suchText = "" then
projekt.'Alle Vorhandenen Materialien'
else
if suchText = "x$x" then
getMaterialOverNr(projekt, filterTextNrs)
else
if contains(suchText, " + ") then
let splitSuche := split(suchText, " + ");
let ergebnis := projekt.'Alle Vorhandenen Materialien';
for x in splitSuche do
let temp := filterMaterial(projekt, x, filterTextNrs);
ergebnis := ergebnis[contains(temp.Nr, this.Nr)]
end;
ergebnis
else
if contains(suchText, " / ") then
let splitSuche := split(suchText, " / ");
let item1 := item(splitSuche, 0);
let ergebnis := filterMaterial(projekt, item1, filterTextNrs);
for x in splitSuche[this != item1] do
let temp := filterMaterial(projekt, x, filterTextNrs);
ergebnis := projekt.'Alle Vorhandenen Materialien'[contains(array(ergebnis.Nr, temp.Nr), this.Nr)]
end;
ergebnis
else
if contains(suchText, " - ") then
let splitSuche := split(suchText, " - ");
let item1 := item(splitSuche, 0);
let ergebnis := filterMaterial(projekt, item1, filterTextNrs);
for x in splitSuche[this != item1 and this != "x§x"] do
ergebnis := ergebnis[not Hersteller like x and not Oberbegriff like x and not Herstellernummer like x]
end;
ergebnis
else
filterMaterial(projekt, suchText, filterTextNrs)
end
end
end
end
end
end;
function fusionMaterial(project : 'Filterung Ansicht',filter1 : text,filter2 : text,operator : text) do
let material1 := getMaterialOverNr(project, filter1);
let material2 := getMaterialOverNr(project, filter2);
let result := project.'Alle Vorhandenen Materialien';
switch operator do
case "and":
(result := material1[contains(material2.Nr, this.Nr)])
case "or":
(result := project.'Alle Vorhandenen Materialien'[contains(material1.Nr, this.Nr) or contains(material2.Nr, this.Nr)])
case "except":
(result := material1[not contains(material2.Nr, this.Nr)])
end;
concat(result.Nr)
end;
function findKlammerStart(text : text) do
let chars := split(text, "");
let found := -1;
for i from 0 to length(text) - 1 do
if item(chars, i) = "(" then found := i end
end;
found
end;
function findKlammerEnde(text : text,startPos : number) do
let tiefe := 1;
let chars := split(text, "");
let found := -1;
for i from startPos + 1 to length(text) do
if item(chars, i) = "(" then
tiefe := tiefe + 1
else
if item(chars, i) = ")" then
if tiefe = 1 then found := i end;
tiefe := tiefe - 1
end
end
end;
found
end;
function findOperator(text : text,start : number,pos : number) do
let restText := substring(text, start, pos);
if contains(restText, " + ") then
"and"
else
if contains(restText, " / ") then
"or"
else
if contains(restText, " - ") then
"except"
else
""
end
end
end
end;
function klammerAufteilung(project : 'Filterung Ansicht',suche : text) do
let startSuche := suche;
let filterTextNrs := "";
let weiterSuchen := true;
let zeilenumbruch := "
";
let DebugText := "Start: " + startSuche + zeilenumbruch;
while weiterSuchen do
if not (contains(startSuche, "(") and contains(startSuche, ")")) then
weiterSuchen := false;
DebugText := DebugText + "Keine Klammern mehr gefunden" + zeilenumbruch
else
let klammerStart := findKlammerStart(startSuche);
DebugText := DebugText + "Klammer-Start gefunden bei: " + klammerStart + zeilenumbruch;
if klammerStart < 0 then
weiterSuchen := false;
DebugText := DebugText + "Kein Klammer-Start gefunden" + zeilenumbruch
else
let klammerEnde := findKlammerEnde(startSuche, klammerStart);
DebugText := DebugText + "Klammer-Ende gefunden bei: " + klammerEnde + zeilenumbruch;
if klammerEnde < 0 then
weiterSuchen := false;
DebugText := DebugText + "Kein Klammer-Ende gefunden" + zeilenumbruch
else
let inKlammerText := substring(startSuche, klammerStart + 1, klammerEnde);
DebugText := DebugText + "Klammerinhalt: '" + inKlammerText + "'" + zeilenumbruch;
let material := getProjektMaterial(project, inKlammerText, filterTextNrs);
let materialNrs := concat(material.Nr);
DebugText := DebugText + "Material Nummern: " + materialNrs + zeilenumbruch;
let klammerMitInhalt := substring(startSuche, klammerStart, klammerEnde + 1);
startSuche := replace(startSuche, klammerMitInhalt, "x§x");
DebugText := DebugText + "Suchtext nach Ersetzung: '" + startSuche + "'" + zeilenumbruch;
filterTextNrs := materialNrs
end
end
end
end
;
DebugText := DebugText + "Endgültiger Suchtext: '" + startSuche + "'" + zeilenumbruch;
DebugText := DebugText + "Gespeicherte Nummern: " + filterTextNrs + zeilenumbruch;
let materialNrs := "";
if startSuche != "x§x" then
let material := getProjektMaterial(project, startSuche, filterTextNrs);
materialNrs := concat(material.Nr);
DebugText := DebugText + "Material aus Resttext: " + materialNrs + zeilenumbruch
else
materialNrs := filterTextNrs
end;
project.(DebugTextInfo := DebugText);
getMaterialOverNr(project, materialNrs)
end;
let me := this;
let suche := Suche;
klammerAufteilung(me, suche)
Josef_Koenig
vor 8 Tagen
Gemeldet - anzeigen
Ich kann den Code leider nicht überprüfen. Versuche ich, ihn auszutauschen, erhalte ich eine Fehlermeldung: "Die Funktion darf keine Datenänderungen vornehmen."
Aber eine ganz andere Frage an die NINOX-Community bzw. an die Firma NINOX: Lässt sich diese geniale Suchfunktion nicht auch für die globale Suche implementieren? Das wäre eine große Bereicherung der Suchmöglichkeiten!
Lamping & Reisig Gmbh & Co.KG
LuRLorenz
vor 6 Tagen
Gemeldet - anzeigen
Für die Ansicht müsstest du die Zeile 164 "project.(DebugTextInfo := DebugText);" löschen.
Zu der anderen Frage, kann nicht ganz einschätzen wie effizient die Suche über sehr große Datenmengen wäre. Bei uns sind es glaube höchstens 500 Datensätze. Aber wenn das Ninox intern gemacht werden würde, dann müsste es ja auch nochmal effizienter möglich sein.