German WebView Table Funktionen ausführen

Anne

Member
Licensed User
Longtime User
Hallo Klaus

In DBUtil in der Sub ExecuteHtml wird eine Tabelle aufgebaut, deren Inhalt ich etwas verändert habe, um an den Inhalt bestimmter Zellen zu gelangen. Ich habe allerdings nur der WebViewTable einen Namen verpasst, um auf diese ID zuzugreifen. Was ich nicht will ist, die Tabelle bei jeder Zelle um eine Onclick-Funktion zu erweitern, das bläst die Tabelle sehr auf. Was ich auch nicht will, ist die gesamte SQL-Tabelle zuerst in eine Memory-Tabelle zu übernehmen, damit ich über die die Felder auf die Inhalte schliessen kann. Dies bedeutet nämlich, dass ich u.U. die gesamte SQL-Tabelle mindestens zweimal im internen Speicher habe, einmal als Memory-Tabelle und einmal als HTML-Tabelle. Ausserdem ist die Original SQLite-Tabelle auch noch dort. Selbstverständlich kann ich durch Selects die Menge in HTML und Memory einschränken, aber das hängt vom User ab.

Die Funktion in JavaScript, die ich gern beim Klick durchführen möchte, sieht so aus:
B4X:
<script>
function ShellCell(i)
{
var x = document.getElementByID('WebView').rows[i].cells;
return x[0].innerhtml;
} 
</script>

Ich habe nun mit WebviewExtras.ExecuteJS und WebViewExtras.ExecuteJS
(Warwound Juni 2011) , (Warwound August 2011) und frühere durchgearbeitet, aber ich bekomme keine Antwort von meinem Javascript.

Ich hab's mit der CellClickhandler probiert, aber nur bei jedem <TR>, weil ich eigentlich nur den Schlüssel brauche und nicht die ganze Zeile.

Aber ich fürchte, dass ich schon jede <TD> mit einem OnClick versehen muss. Irgendeinen Tod muss ich sterben. Siehst du das auch so?
Vielleicht weisst du noch eine bessere Lösung?
Am liebsten wäre es mir, wenn ich mit WebView_OverrideURL arbeiten könnte, denn da sind Click-Zeile und Kolonne schon vorhanden. Nur wie komme ich von da aus bloss auf den Zelleninhalt?

Vielen herzlichen Dank für deine Hilfe. Gruss Anne
 

klaus

Expert
Licensed User
Longtime User
Hallo Anne,
Wie ist Deine Datenbank aufgebaut ?
Hast Du eine ID Spalte ?
Wenn ja, kannst Du mit
SQL.ExecQuerySingleResult("SELECT xxx FROM Table WHER ID = " & row + 1)
den Wert auslesen (der erste ID Wert ist 1, die erste Row aber 0).
Falls Einträge einmal gelöscht wurden sind die ID Werte nicht mehr fortlaufend dann müsstest Du diese beim Einlesen der Datenbank in eine List laden und mit dem Row Wert den richtigen ID zurückbekommen.

Beiliegend ein kleines Programm das obenstehendes veranschaulicht.
Das Programm ist eine Erweiterung des LoadIntoWebView Beispiels aus dem User's Guide.

Best Grüsse.
 

Attachments

  • LoadIntoWebView.zip
    10.9 KB · Views: 339

Anne

Member
Licensed User
Longtime User
Danke Klaus für deine schnelle Antwort.

Ich hätte trotz allem noch deutlicher werden sollen. Ich schreibe ein Programm, das es einfachen Usern erlauben soll, Datenbanken inkl. Struktur anzulegen, Daten zu erfassen, zu ändern und zu löschen und darin auf jede erdenkliche Art zu recherchieren. Der User gibt den Datenbank- und Tabellennamen aus einer Auswahl (Spinner) an und danach ist es an mir, die Struktur herauszufinden, die Selects aufzubauen, etc. und das alles ohne die Struktur zu kennen. Die Struktur hole ich mir aus PRAGMA, wenn ich nur die Feldnamen brauche, dann genügen mir die Daten aus einem Cursor.
Der Datenbildschirm wird vollständig dynamisch aufgebaut, da ich zu Designzeiten weder die Anzahl Felder noch ihre Definitionen kenne.
Die Uebersicht über alle gewünschtren Daten ist in einem WebView, wo der User irgendwo hin tappt (oder klickt) und ich muss dann den SchlüsselInhalt ermitteln, damit ich mit SQL das entsprechende Record finden kann. Der Schlüssel muss sich nicht unbedingt an erster Position befinden, ist aber empfohlen.
Wenn ich das Record in der Datenbank gefunden habe, kann ich es zum Ändern auf den Screen übertragen - aber alles über arrays und Listen, denn ich kenne ja die Struktur nicht. Ich könnte allerdings auch die ganze Zeile aus dem Webview holen. Beide Wege sind genehm. Nur leider, wenn ich den Schlüsselinhalt nicht bekomme, kann ich die SQL-Variante vergessen. Und wenn ich die Daten aus der Tabelle nicht in mein Programm bekomme, wird aus der zweiten Variante nichts.
Wenn du nicht weiter weisst, dann muss ich weiterpröbeln. Irgendwie werde ich das schon schaffen. Ich hatte nur auf eine Abkürzung gehofft.
Danke vielmals für die rasend schnellen Responsezeiten deinerseits. Gruss Anne.
 
Last edited:

Anne

Member
Licensed User
Longtime User
Hallo Klaus

Ich danke dir für deine Mühe. Wenn es zu einem Problem (noch) keine Lösung gibt, dann muss man sie finden. Das geht aber weit über "Support" hinaus. Du musst nämlich nicht meine Arbeit machen. Ich dachte nur an eine Abkürzung.
Wenn ich eine brauchbare Lösung habe, dann schick ich sie dir. Ich bin mal gespannt, wie lange das geht.
Die Arbeit von Erel sieht sehr gut aus. Vor vier, fünf Wochen wäre ich froh darüber gewesen, aber das meiste habe ich selbst herausgefunden, wenn auch mit deiner Hilfe.
Sorry, dass ich deine Lösung mit der Memory-Tabelle der Keys abgelehnt habe, aber ich wehre mich so lange gegen redundante Daten im Speicher, bis ich alles ausprobiert habe.
Trotz allem - ich finde es ganz toll, wie ihr euch ins Zeug legt. Ich habe auch schon viel von euch gelernt, obwohl das Thema nicht immer unbedingt zu meinem jetzigen Problem passt.Ich habe alle eure Lösungen aufbewahrt, vielleicht läuft mir das passende Problem einmal vor die Nase.

Bis zum nächsten Problem. Gruss Anne :sign0098:
 

klaus

Expert
Licensed User
Longtime User
Hallo Anne,
Mit folgendem Code bekommst Du die PRIMARY Schlüsselinhalte ohne zu wissen in welcher Spalte sie sich befinden :
B4X:
Dim IDList As List

IDList.Initialize
Cursor1 = SQL1.ExecQuery("SELECT rowid FROM " & DBTableName)
For i = 0 To Cursor1.RowCount - 1
    Cursor1.Position = i
    IDList.Add(Cursor1.GetLong2(0))
Next
Bei mir funktioniert es.

Beste Grüsse.
 

Anne

Member
Licensed User
Longtime User
Hallo Klaus

Ich dachte unser Mailaustausch sei zu Ende, aber du hast mir tatsächlich eine Lösung gebracht, die ich noch nicht kannte und die sehr viel kürzer ist als meine. Ich habe nämlich "PRAGMA table_info(table-name)" benutzt, bin mit dem Cursor durch alle Felder geturnt und habe das Feld "pk" abgefragt, ob on oder off.
Näheres findet man unter Pragma statements supported by SQLite. Pragma liefert unheimlich viele Informationen, aber dein Weg ist für meinen Zweck viiiiiiiel kürzer.
Vielleicht fallen dir noch mehr solche Goodies ein. Ich sage dir trotzdem mal wieder au revoir.
Gruss Anne.
 

klaus

Expert
Licensed User
Longtime User
Ich habe nämlich "PRAGMA table_info(table-name)" benutzt ...
Da hatte Ich auch reingeschaut und hatte gehofft dass man eine Spalte mit dem Type INTEGER PRIMARY KEY finden würde.
INTEGER ja aber PRIMARY KEY nein.
Wenn es um SQLite geht suche Ich immer hier und rowid hier.

Beste Grüsse.


Beste Grüsse.
 

Anne

Member
Licensed User
Longtime User
Hoi Klaus

Da hab' ich gedacht, ich könnte dir mal was zeigen, was du noch nicht kennst, aber Pustekuchen. In der Zwischenzeit hab' ich mein Coding auch wiedergefunden, das das Problem auch löst. Hier ist es:

B4X:
    Dim cid(Main.NumberofColumns) As Int
   Dim colName(Main.NumberofColumns) As String
   Dim Typ(Main.NumberofColumns) As String
   Dim NotNull(Main.NumberofColumns) As Boolean
   Dim defValue(Main.NumberofColumns) As String
   Dim pk(Main.NumberofColumns) As Boolean

    Dim txt  As String
   
    txt = "PRAGMA table_info(" & Main.DBTableName & ")"
    CursorPrag = Main.SQLDatabase.ExecQuery(txt)

   For i = 0 To cursorPrag.RowCount - 1
         cursorPrag.Position = i
        cid(i) = cursorPrag.GetString("cid")
        colName(i) = cursorPrag.GetString("Name")
        Typ(i) = cursorPrag.GetString("Type")
        NotNull(i) = cursorPrag.GetString("notnull")
        defValue(i) = cursorPrag.GetString("dflt_value")
        pk(i) = cursorPrag.GetString("pk")
             If pk(i) = True Then 
       [B]Main.PrimKey = i[/B]
        End If   
   Next
    
   CursorPrag.Close

So können auf den Primkey alle Module zugreifen und der "PRAGMA" muss nur einmal durchgeführt werden.

Fast hätte ich meine Grüsse vergessen. Grüessli Anne
 

klaus

Expert
Licensed User
Longtime User
Hallo Anne.

Danke für die Info, habe etwas dazu gelernt.
In der PRAGMA table_info fehlte mir die Definition eines Parameters.
Hatte noch nicht die Zeit genommen weiter zu Schnüffeln, brauche es jetzt nicht mehr.
Leider ist das in dieser Dokumentation nicht klar angegeben.
Wo hast Du die Definitioen gefunden?
Die reservierten Spaltennamen sind da leider auch nicht angegeben.
Ich hatte angefangen die PRAGMA und die rowid Methoden in den User's Guide einzubinden kann es jetzt fertig machen.

Die PRAGMA Methode hat leider den Nachteil dass nichts gefunden wird wenn in Database Create keine Spalte mit PRIMARY KEY definiert wurde.
Mit SELECT rowid funktioniert es aber auch wenn keine PRIMARY KEY Spalte definiert wurde.

Nochmals Danke und Beste Grüsse.
 
Last edited:

Anne

Member
Licensed User
Longtime User
Hallo Klaus

Ich wollte dir ursprünglich dieses Bildchen mitschicken, aber der Attachment-Manager hat gemotzt, es wäre zu gross. So habe ich es um 50% verkleinert. Ich hoffe, du kannst es noch lesen.
Ich habe mir den Google SQL-Mnager zugetan als ich mit B4A anfing. So bin ich in SQLite eingestiegen. Funktioniert ganz ordentlich und drum bin ich dabei geblieben.
Ich habe mir in zwischen Erels SQLite-Viewer mal angesehen, leider läuft er genauso wenig wie meine Lösung.
Ich glaube das liegt weniger an Erel als an mir. Weder erscheint das Menu noch werde ich nach irgendwelcher Eingabe gefragt. Verwmutlich fehlt dem armen Programm DBUtils. Ich grabe weiter, verlass dich drauf.
Ein weiteres Grüsschen von Anne
 

Attachments

  • pragma.jpg
    pragma.jpg
    54.8 KB · Views: 303

klaus

Expert
Licensed User
Longtime User
Hallo Anne,
Ich hatte mir, als Ich mit SQLite anfing, SQLite2009Pro zugelegt (gratis).
Habe jetzt auch das PRAGMA mit einer Datanbank darin gestartet und siehe da, Ich sehe natürlich das gleiche wie Du.
Hatte so was noch nie versucht.
Es ist doch schön wenn man jeden Tag noch was dazu lernt :).

Beste Grüsse.
 

Anne

Member
Licensed User
Longtime User
Hallo Klaus
Jetzt hat mich euer Forum-Programm erwischt. Ich hatte beim ersten Mail nicht bemerkt, dass jetzt eine zweite Seite gestartet wurde und hatte gemeint, das erste Mail sei im Nirwana gelandet. Also nochmal dasselbe in grün. Und das war dann einmal zuviel. Ich habe mich allerdings gerade noch schwach erinnert, dass man das überflüssige Mail löschen kann, was ich gerade getan habe.
Ich habe übrigens den Denkfehler, den ich im Zusammenhang mit Javascript gemacht habe, herausgefunden: Ich hatte immer versucht, mit dem Interface HTML und Javascript zu manipulieren und nur einen returnwert erwartet. Es ist aber genau umgekehrt: Man muss das Javascript starten und diesem einen Subnamen im B4A-Programm mittteilen, das dann die Werte aus dem Javascript be- und verarbeitet. Ausserdem sind als Argumente (Parameter) ausschliesslich String-Werte erlaubt.
Ich glaube jetzt geht's vorwärts. Das schaffe ich heute noch!
Mindestens fünf Grüsse von Anne
 
Last edited:

Anne

Member
Licensed User
Longtime User
Hallo Klaus

Ich habe gemeint, ich hätte das Ei des Kolumbus gefunden, aber leider nicht. Die Javascript-Ausführung funktioniert einfach nicht, ob ich jetzt Aposthrophe um das document.getElementById mache oder nicht, ob ich diesen Javascript-Befehl direkt in den Aufruf übernehme oder nicht, es tut einfach nichts. Den Javascript-Befehl habe ich getestet mit alert und er läuft einwandfrei, auch der Typ ist richtig, ich übergebe einen String-Typ. Es ist zum Davonlaufen.

In DBUtils habe ich eine klitzekleine Kleinigkeit geändert. Die Table hat in der Sub ExecuteHtml eine ID bekommen. Das sieht dann so aus:

B4X:
Sub ExecuteHtml(SQL As SQL, Query As String, StringArgs() As String, Limit As Int, Clickable As Boolean) As String
    ...
    sb.Append("<table id='WebView'><tr>").Append(CRLF)
    ...

Im Modul DBEdit (ist meins) habe ich unter Globals die folgenden Definitionen vorgenommen:

B4X:
Sub Globals
      Dim WebViewSettings1             As WebViewSettings
      Dim WebViewExtras1               As WebViewExtras
      Dim webViewTable                As WebView

und unter Activity_Create für die Settings und Extras die Interfaces aktiviert. Übrigens: Selbstverständlich ich die beiden Libraries geladen.

B4X:
Sub Activity_Create(FirstTime As Boolean)
      ..
      WebViewSettings1.setDefaultFontSize (webViewTable, 11)
      WebViewExtras1.addJavascriptInterface(webViewTable, "B4A")   
      ..

Da mir DButils bereits wunderschön die angeklickte Zelle ermittelt, habe ich meine Ergüsse in der Sub Webviewtable_OverrideUrl angefügt. Die Routine, die das blöde Ding aufrufen soll, ist gerade dahinter.

B4X:
Sub WebViewtable_OverrideUrl (Url As String) As Boolean
   
   Dim values()          As String
    Dim col, row          As Int
   Dim HtmlCode          As String
   Dim Script            As String
   
   values = Regex.Split("[.]", Url.SubString(7))
   col = values(0)
   row = values(1)

    Script = "B4A.CallSub('CellClickHandler', true, " & _
    "document.getElementById('WebView').rows[" & row & "].cells[" & col & "].innerHTML;"
   Log(Script)
   WebViewExtras1.executeJavascript(webViewTable,Script) 
    Return True 'Don't try to navigate to this URL
End Sub

Sub CellClickHandler(Wert As String)
     Log(Wert)
End Sub

Es tut mir ausserordentlich leid, dass ich dir nicht einfach mal eine Lösung präsentieren kann, aber vorher brauche ich noch mal deine Hilfe.

Vielen, vielen Dank. Heute abend habe ich etwas vor, darum stelle ich meine Klapf für jetzt ab. Ich habe genug Frust erlebt.

Tschau Anne.
 

klaus

Expert
Licensed User
Longtime User
Hallo Anne,
Entschuldige die etwas verspätete Antwort.
Als Ich dein Post gelesen hatte, hatte Ich keine direkte Antwort und habe das Problem dann etwas beseite gelasssen.
Gestern habe Ich den ganzen Tag an einem meiner Projekte gearbeitet.
Habe jetzt mal näher reingeschaut und komme zum Schluss dass Ich hier leider nicht weiter helfen kann denn Ich habe in diesem Bereich gar keine Erfahrung.

Muss da auch mal eines Tages tiefer reinschauen.

Beste Grüsse.
 

Anne

Member
Licensed User
Longtime User
Hallo Klaus

Auch das gibt es! Du hast keine Lösung?! Und das gibst du einfach so zu? Ich bin verblüfft über deine Charakterstärke und dass du einem "fast-Newbie" das auch noch zugibst.
Sorry, ich hatte Ähnliches schon vermutet. Sonst bist du so irrsinnig schnell und diesmal nicht. Ich habe den letzten Eintrag ins Englische übersetzt und mich an Warwound gewandt. Er ist zwar selbst ziemlich im Druck, aber vielleicht ist das etwas Klitzekleines, was er mit einem Blick sieht, wo ich mit Blindheit geschlagen bin.
Also - nichts für ungut - du bist für mich immer noch das grösste Ass. Und denk' immer dran: Wer alles kann, kann nichts perfekt. Besser du bist auf deinen Gebieten der Grösste als überall mittelmässig.
Viele Grüsse Anne.
 

Anne

Member
Licensed User
Longtime User
Hallo Klaus

Heureka!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Endlich, endlich ist es mir gelungen. Es war wirklich nur eine klitzekleine Kleinigkeit:

B4X:
Script = "B4A.CallSub('CellClickHandler',true,document.getElementById('WebView').rows[" & row& "].cells[" & col & "].innerHTML)"

Bitte beachte am Schluss hinter "innerHTML" ist das Semicolon verschwunden, dafür steht da jetzt eine Klammer.

Der Rückgabewert enthält wie bei der Sub WebViewTable_Override auch den "Row"- und den "Col"-Wert und muss wie dort auseinander genommen werden.
Wow!!! Für heute ist Schluss. Heute Nacht schlafe ich mal ohne WebView-Träume.

Bis demnächst mal wieder und viele liebe Grüsse Anne
 
Top