1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Code-Jack

Beiträge von Code-Jack

  • ListView füllen und ProgressBar

    • Code-Jack
    • 20. November 2018 um 13:09

    Jupp, diesen Ansatz hatte ich schon aus Deinem Posting Nr. 7 herausgelesen, autobert.

    Dein Beispiel funzt und ist auch bei Erweiterung auf 1000 Datensätze angenehm flott.

    Heute Abend baue ich das mal real in mein Programm ein. Mal schauen, ob es dann immer noch flott ist (ich habe mehr Felder pro Datensatz).

    Vermutlich macht es Sinn, zudem noch alpines' Tipp aufzugreifen und das Array zuvor passend zu kreieren. Denn möglicherweise verursacht _SQLite_GetTable2d() massenhaft ReDims (muss ich testen, ob dem so ist).

    -------------

    Übrigens ist das mal wieder so ein Punkt, wo die Hilfefunktion gerne etwas ausgebaut werden könnte.

    Wenn das Umfärben von ListView-Einträgen nur bei einzeln kreierten Einträgen klappt, jedoch kläglich versagt, wenn man zuvor ein ganzes Array übergeben hat, dann müsste diese wichtige Info in die Hilfe!

    Die sinnlose Probiererei hat mich Stunden gekostet, inklusive der Forenpostings. Euch hilfreiche Geister hat es ebenfalls Zeit gekostet (vielen Dank dafür!).

    Und noch immer, trotz allem RTFM und allerhand Probiererei, blicke ich nicht völlig klar, in welchen Fällen $GUI_BKCOLOR_LV_ALTERNATE das tut, was man erwartet, oder es eben nicht tut.

    Schade, dass die Hilfe dieses spezielle Flag bei GUICtrlCreateListView und bei GUICtrlCreateListViewItem zwar im Text erwähnt, dessen konkreten Einsatz dort aber im Beispielcode nicht demonstriert.

    Immerhin: Bei GUICtrlSetBkColor wird der Einsatz auch im Quelltext gezeigt, dort wird aber gleich wieder verwirrt/relativiert mit den mehrfach vorhandenen Zeilen:

    ; The following line could be dropped as the background color is taken from the listview.

    - Sicher versteht man das irgendwann, wenn man lange genug herumgetüftelt und sich mehrmals quer durch die Hilfe geackert hat. Aber ich habe den Eindruck, dass selbst Ihr erfahrenen Power-User nicht gerade auf Anhieb durchgeblickt habt, oder?

    Für einen Einsteiger finde ich die Hürde schon ziemlich hoch!

    Der Text macht Hoffnung, dass $GUI_BKCOLOR_LV_ALTERNATE der Bringer wäre, doch man probiert und probiert, es geht jedoch partout nicht.

  • ListView füllen und ProgressBar

    • Code-Jack
    • 19. November 2018 um 23:00

    Wenn alle Stricke reißen, dann muss ich wohl den von Dir verlinkten Weg gehen, Bitnugger.

    Zuvor habe ich es aber mal "klassisch" probiert, jeden zweiten Eintrag der bereits gefüllten ListView in einer Schleife umzufärben, jedoch ohne Erfolg:

    C
    Local $idLVI
    ;GUICtrlSetBkColor($idListView, $GUI_BKCOLOR_LV_ALTERNATE)
    GUICtrlSetBkColor($idListView, 0xA0E68C)
    
    For $i = 1 to 20 Step 2 ;$iTreffer Step 2
       $idLVI = _GUICtrlListView_MapIndexToID($idListView, $i)
       ConsoleWrite("$i = " & $i & "  $idLVO = " & $idLVI & @CRLF)
       GUICtrlSetBkColor($idLVI, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)
       ;_GUICtrlListView_SetTextBkColor($idLVI, 0xB9D1EA)
    Next

    Mich wundert, dass ...MapIndexToID laut Hilfe angeblich eine echte, beständige ID zurück liefern soll.

    In der Konsole erscheint bei mir:

    $i = 1 $idLVO = 1

    $i = 3 $idLVO = 3

    $i = 5 $idLVO = 5

    $i = 7 $idLVO = 7

    $i = 9 $idLVO = 9

    $i = 11 $idLVO = 11

    $i = 13 $idLVO = 13

    $i = 15 $idLVO = 15

    $i = 17 $idLVO = 17

    $i = 19 $idLVO = 19

    Ich hätte eher eine Art Handle erwartet, als Rückgabewert.

    GUICtrlSetBkColor scheint mit dieser Art von ID jedenfalls ebenfalls unzufrieden zu sein.

  • ListView füllen und ProgressBar

    • Code-Jack
    • 19. November 2018 um 19:21

    Sehr gute Tipps, danke!

    Ich habe mal autoberts Vorschlag umgesetzt: Statt einer Schleife verwende ich nun _SQLite_GetTable2d.

    Das hat die Sache wirklich deutlich beschleunigt, große Klasse! :thumbup:

    Was mir aber partout nicht gelingen will, ist das alternierende Einfärben der ListView-Einträge.

    Kreieren tue ich die ListView am Programmbeginn so:

    C
    $idListView = GUICtrlCreateListView($sListViewHeader, 10, 40, 1150, 260, $LVS_SHOWSELALWAYS, BitOr($LVS_EX_FULLROWSELECT, $LVS_EX_HEADERDRAGDROP))  ;# Spaltenköpfe per Maus umsortierbar!
    GUICtrlSetBkColor(-1, 0xFFFFFF) ; Color weiß
    GUICtrlSetBkColor(-1, $GUI_BKCOLOR_LV_ALTERNATE)
    GUICtrlSetFont(-1, 10, 400, 0, "Arial")

    Und meine jüngst umgebaute Routine zum Befüllen der ListView sieht jetzt so aus:

    C
    Func _ListViewFill($sSQLiteBefehl)
      ;# Hier wird die ListView mit den aus SQLite ausgelesenen Daten befüllt.
      ;# Je nach übergebenem $sSQLiteBefehl wird entweder nur ein einzelner Datensatz in die ListView eingefügt, oder es werden mehrere Einträge, oder gar
      ;# die komplette Datenbank, in die ListView übertragen.
      ;# Jeder Datensatz aus SQLite fließt dabei zunächst in das eindimensionale Array $aDatentaxi ein.
    
      Local $hQuery
    
      Local $_sTable = 'Mainboardverwaltung'
      GUICtrlSetData($idProgressbar1, 0)                               ;# Die Fortschrittsanzeige auf Null setzen ...
      GUICtrlSetState($idProgressbar1, $GUI_SHOW)                   ;# ... und einblenden.
    
      $sTmp = _GUICtrlListView_BeginUpdate($idListView)             ;# Wir haben zeitintensives mit der ListView vor. Änderungen daher nicht instantan anzeigen.
      _GUICtrlListView_DeleteAllItems($idListView)                  ;# ListView komplett leeren.
    
      If $sSQLiteBefehl = "" Then                                   ;# Wenn der Function ein Leerstring übergeben wurde, ...
        $sSQLiteBefehl = "SELECT count(*) FROM " & $_sTable & ";"   ;# ... dann soll die gesamte Datenbank ausgelesen werden.
      EndIf
    
    
      Local $aQuery
    
      Local $iTreffer = _SQLite_CountRows('Mainboardverwaltung', $sSQLiteBefehl)     ;# Ermittelt vorweg die Anzahl der gleich einzulesenden Datensätze.
    ;consolewrite("Treffer = " & $iTreffer & @crlf)
    
    
    ;_GUICtrlListView_SetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)
    ;_GUICtrlListView_SetBkColor($idListview, 0xF0E68C)
    ;_GUICtrlListView_SetTextColor($idListview, 0x79D1EA)
    ;_GUICtrlListView_SetTextBkColor($idListview, 0xB9D1EA)
    ;GUICtrlSetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)
    ;GUICtrlSetBkColor(-1, $GUI_BKCOLOR_LV_ALTERNATE)
    GUICtrlSetBkColor($idListview, $GUI_BKCOLOR_LV_ALTERNATE)
    
    #cs
    Nimm anstelle von _SQLite_Query _SQLite_GetTable2d.
    Wenn dann noch das SQL Statement analog zur LV aufebaut ist kannst du auch noch anstelle
    von GUICtrlCreateListViewItem(um eine LV-Zeile zu erstellen) _GUICtrlListView_AddArray verwenden
    und das komplette Egebnis auf eimal einzutragen.
    Schnellste Methode
    Falls es aber das Egebnis nicht zulässt, musst du in einer Schleife durch das erhaltene Array
    (Ergebbnis von _SQLite_GetTable2d) gehen und GUICtrlCreateListViewItem verwenden.
    Selbst diese Methode ist noch deutlich schneller als dein Ansatz mit _SQLite_Query.
    #ce
    
      Local $aResult[$iTreffer][$iFeldNrMax + 1], $iRows, $iColumns, $iRval                            ;# Ein Array kreieren, in das die Datensätze eingelesen werden.
      $iRval = _SQLite_GetTable2d(-1, $sSQLiteBefehl, $aResult, $iRows, $iColumns)                     ;# Die SQLite-Datensätze ins Array einlesen.
      if $iRval = $SQLITE_OK Then                                                                      ;# Wenn das geklappt hat ...
        ;_SQLite_Display2DResult($aResult)
        ;Msgbox(-1, "", "Zeilen: " & $iRows & @CRLF & "Spalten: " & $iColumns & @CRLF & "0 = " & $aResult[0][0] & @crlf & "1 = " & $aResult[0][1] & @crlf & "2 = " & $aResult[0][2] & @crlf)
        _GUICtrlListView_AddArray ($idListView, $aResult )                                             ;# ... dann das Array in die Listview "schütten" ;-)
      Else
        MsgBox($MB_OK, "Fehler:", "Die SQLite-Datenbank konnte nicht ins Array kopiert werden.")       ;# Falls es aber nciht geklappt haben sollte, User informieren.
      EndIf
    
    #cs
      Local $i = 0
      Local $iProzentwert = 0
      Local $iLast = 0
      _SQLite_Query(-1, $sSQLiteBefehl, $hQuery)                                                        ;# Die SQLite-Suchfunktion parametrieren ...
      While _SQLite_FetchData($hQuery, $aDatentaxi, False, False) = $SQLITE_OK                          ;# ... anschließend fröhlich Suchtreffer ansammeln ...
        GUICtrlCreateListViewItem(_ArrayToString($aDatentaxi, '|', 1, 21), $idListView)                 ;# ... und diese sogleich in die ListView schreiben ...
        GUICtrlSetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)     ;# ... und dort hübsch herrichten ...
        ;--- Berechnungen für die Fortschrittsanzeige ---\
        $i += 1
        $iProzentwert = Round(100 * $i / $iTreffer)
        if $i <> $iLast then
          $iLast = $i
          GUICtrlSetData($idProgressbar1, $iProzentwert)                                                  ;# ... außerdem die Fortschrittsanzeige aktualisieren ...
        EndIf
        ;--- Berechnungen für die Fortschrittsanzeige ---/
      WEnd                                                                                              ;# ... bis nichts mehr gefunden wird.
    #ce
    
      _SQLite_QueryFinalize($hQuery)    ;# Beendet die SQL-Abfrage.                                     ;# Zuletzt SQLite noch über unsere volle Befriedidgung informieren.
    
      _GUICtrlListView_RegisterSortCallBack($idListView)             ;### Klärungsbedarf! ###
    
    
    ;_GUICtrlListView_SetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)
    ;_GUICtrlListView_SetBkColor($idListview, 0xF0E68C)
    ;_GUICtrlListView_SetTextColor($idListview, 0x79D1EA)
    ;_GUICtrlListView_SetTextBkColor($idListview, 0xB9D1EA)
    ;GUICtrlSetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)
    ;GUICtrlSetBkColor(-1, $GUI_BKCOLOR_LV_ALTERNATE)
    
    
      $sTmp = _GUICtrlListView_EndUpdate($idListView)                ;# Die ListView-Anzeige insgesamt aktualisieren.
      GUICtrlSetState($idProgressbar1, $GUI_HIDE)                    ;# Die Fortschrittsanzeige wieder ausblenden.
    EndFunc   ;==>_ListViewFill
    Alles anzeigen

    (Habe es in der Codebox notgedrungen als "C-Code" markiert, weil man im Forum"AutoIt" nicht mehr zur Auswahl hat.)

    Das Resultat ist jedenfalls eine ruckzuck und ordnungsgemäß prall gefüllte ListView, aber leider mit schneeweißem Hintergrund.

    - Nix mit alternierend gefärbten Einträgen. :'-(

    Alle meine Versuche, das zu ändern, scheiterten kläglich (und wie so oft, hilft die Hilfedatei nicht wirklich).

  • ListView füllen und ProgressBar

    • Code-Jack
    • 18. November 2018 um 22:28

    Hallo alpines,

    nein, das mit der Progressbar und der Schleife ist nicht der Punkt.

    Die Schleife selbst wird ja ratzfatz durchlaufen und zugleich die PrograssBar bis zum Anschlag gefüllt.

    Das geht aus den beiden Zeilen unter der Schleife hervor, denke ich.

    ... ABER - ich habe das Problem eben gerade selbst entdeckt (schäm!) - die Progressbar erwartet Werte im Bereich bis maximal 100, ist also auf Prozent gebürstet.

    Das war in der Programmiersprache, in der ich zuletzt unterwegs war, anders.

    GANZ DOLL SCHÄM!

    OK, die Schleife wird bei 1600 Datensätzen also doch nicht so ruckzuck durchlaufen, wie meine Progressbar den irrigen Anschein erweckte, die ja schon bei 100 am Anschlag war, ergo lange vor den 1600 Schleifen-Durchläufen ... <:-(

    Bin nun schlauer, danke für die Antwort!

    Jetzt muss ich mich gezielt darum kümmern, die Schleife zu beschleunigen.

    Die Progressbar hatte ich übrigens erst heute eingebaut. Auch ohne die benötigt die Routine ihre knapp 10 Sekunden.

    Die Zeile mit GUICtrlSetData in der Schleife verlangsamt diese übrigens nicht wahrnehmbar.

    (Ist natürlich trotzdem unelegant, die Progressbar bei jedem $i zu aktualisieren, ganz davon abgesehen, dass es - wie nun geklärt - in dieser Form keinen Sinn macht.)

    Btw.: IMHO dürfte die Hilfedatei (für Dussels wie mich) gerne explizit darauf hinweisen, dass bei 100 Schluss ist ...

  • ListView füllen und ProgressBar

    • Code-Jack
    • 18. November 2018 um 20:09

    Ich ärgere mich schon länger darüber, wie lange es dauert, eine ListView zu befüllen.

    Trotz Verwendung von _GUICtrlListView_BeginUpdate($idListView) und seinem Gegenstück, dauert es bei 1600 Datensätzen zu je 32 Feldern fast 10 Sekunden, bis man das Ergebnis in der Listview sieht.

    Auf der Suche nach dem Zeitfresser staunte ich nicht schlecht, denn ich konnte den Verursacher nicht dingfest machen, wohl aber die Stelle, wo es klemmt.

    Die folgende Routine ist zwar isoliert nicht lauffähig (bei Bedarf poste ich das ganze Programm, samt Datenbank), aber ich glaube man versteht bestens, was hier los ist:

    Code
     Func _ListViewFill($sSQLiteBefehl)
      ;# Hier wird die ListView mit den aus SQLite ausgelesenen Daten befüllt.
      ;# Je nach übergebenem $sSQLiteBefehl wird entweder nur ein einzelner Datensatz in die ListView eingefügt, oder es werden mehrere Einträge, oder gar
      ;# die komplette Datenbank, in die ListView übertragen.
      ;# Jeder Datensatz aus SQLite fließt dabei zunächst in das eindimensionale Array $aDatentaxi ein.
      
      Local $hQuery
      $sTmp = _GUICtrlListView_BeginUpdate($idListView)              ;# Wir haben zeitintensives mit der ListView vor. Änderungen daher nicht instantan anzeigen.
      Consolewrite("ListView Begin Update = " & $sTmp & @CRLF)
      _GUICtrlListView_DeleteAllItems($idListView)                   ;# ListView komplett leeren.
    
      _SQLite_Query(-1, $sSQLiteBefehl, $hQuery)                                                        ;# Die SQLite-Suchfunktion parametrieren ...
      Local $i = 0
      While _SQLite_FetchData($hQuery, $aDatentaxi, False, False) = $SQLITE_OK                          ;# ... anschließend fröhlich Suchtreffer ansammeln ...
        GUICtrlCreateListViewItem(_ArrayToString($aDatentaxi, '|', 1, 21), $idListView)                 ;# ... und diese sogleich in die ListView schreiben ...
        GUICtrlSetBkColor(-1, 0xF0E68C) ;# (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)     ;# ... und dort hübsch herrichten ...
        $i +=1
        GUICtrlSetData($idProgressbar1, $i)                                                             ;# ... außerdem die Fortschrittsanzeige aktualisieren ...
      WEnd                                                                                              ;# ... bis nichts mehr gefunden wird.
    
      ConsoleWrite("Der Fortschrittsbalken raste in der Schleife ruckzuck bis zum Anschlag, aber diese Konsolenmeldung hier, kommt erst nach Sekunden. Warum?" & @CRLF)
      ;# ### Klären: wie bekomme ich es hin, dass die ListView gefüllt angezeigt wird, sobald der Fortschrittsbalken rechts am Anschlag ist? ###
    
      _SQLite_QueryFinalize($hQuery)    ;# Beendet die SQL-Abfrage.                                     ;# Zuletzt SQLite noch über unsere volle Befriedidgung informieren.
    
      _GUICtrlListView_RegisterSortCallBack($idListView)             ;### Klärungsbedarf! ###
      $sTmp = _GUICtrlListView_EndUpdate($idListView)                ;# Die ListView-Anzeige insgesamt aktualisieren.
      Consolewrite("ListView End Update = " & $sTmp & @CRLF)
    
      ;# ### Warum lahmt es direkt nach der Schleife? ###
      ;# ### Es dauert bei 1600 Datensätzen noch rund 8 Sekunden, bis die Inhalte in der ListView erscheinen. Warum? ###
      ;# ### So wie es hier ist, ist die ProgressBar nutzlos! ###  
    EndFunc   ;==>_ListViewFill
    Alles anzeigen

    P.S.: In der Codeauswahl des Forums ist "AutoIt" plötzlich nicht mehr verfügbar ...

  • _DownloadWithProgress

    • Code-Jack
    • 18. November 2018 um 17:29

    Vermutlich trifft das den Nagel auf den Kopf, Bitnugger.

    Und wie man auf diesen beiden Seiten nachlesen kann:

    https://www.zdnet.de/88314583/micro…uer-windows-xp/

    https://support.microsoft.com/de-de/help/401…-1-2-in-windows

    ... ist es doch recht frickelig das Update zum Laufen zu bringen. :(

    Das ist aber schade, denn ich hatte die Idee im Kopf, meinem Testgerät ein billiges, minimalistisches, embedded PC-Board zu spendieren, mit einem ebenfalls minimalistischen XP, auf dem dann meine Software läuft.

    Ich hatte mal ein Projekt, wo ich ein Android-Tablet verbaute, mit Anschluss an einen Arduino. Die Arduino Software hatte ich selbst geschrieben, aber die Software für Android musste ich schreiben lassen. Das war ein ewiges Ärgernis, weil ich für jede benötigte Änderung von dem Android-Programmierer abhängig war und ich keine Zeit & Nerven hatte, mich da selbst einzuarbeiten (ich mag Android nicht).

    Aus meiner Sicht wäre es daher wünschenswert, ein abgespecktes Windows-System zu verwenden, auf dem AutoIt läuft. Aber wenn ich mehrere dieser Testgeräte fertige, dann soll die Installation auch nicht ausarten.

    OK, das war ein schwaches Argument; man könnte natürlich ein vorgefertigtes Image einspielen.

    Als Alternative fällt mir noch der IMHO leicht dreckige Workarround ein, dass AutoIt den installierten Webbrowser "fernsteuert". Denn wie man liest, bringen z. B. Firefox und Chrome von sich aus Unterstützung von TLS 1.2 mit. Offenbar umgehen sie das Betriebssystem irgendwie.

    Keine Ahnung, ob das auch auf den Internet Explorer zutrifft, aber meines Wissens tut gerade der IE so einige Dinge am Betriebssystem vorbei.

    Gut, ich habe jetzt einige Dinge zu testen und bedanke mich für die diversen Antworten!

  • _DownloadWithProgress

    • Code-Jack
    • 18. November 2018 um 15:18
    Zitat von autoiter

    Hmm, lässt sich das Problem auf http bzw. https einschränken?

    Wir hatten hier schon Diskussionen darüber. Ich glaube da hatten Leute mit Win 7 Probleme. Ich habe den Thread gerade aber nicht gefunden und bin mir auch nicht sicher..

    Vielleicht machst du einen eigenen Thread auf? ;)

    Nein, mit HTTPS hat es nichts zu tun.

    Der Code aus Oscars Startposting enthält ja Beispiellinks, von denen einer vom Typ HTTPS ist. Und der funzt.


    Zitat von Oscar

    Hast Du eventuell Probleme mit Deiner Internetverbindung?

    Welcher Art könnten diese Probleme sein?

    Ich bin quasi den ganzen Tag online, hangel mich durch diverse Foren, schlage irgendwas auf Wiki nach, lese Nachrichtenportale ... mir ist von Problemen mit der Internetverbindung nichts bekannt.

    Ich habe eben Deinen neuen Code probiert, Oscar.

    Ausgabe in der Console:

    >"D:\Programme\AutoIt3\SciTE-AutoIt3Installer\..\autoit3.exe" /ErrorStdOut "H:\Notebook-Reparatur\Mainboardverwaltung\Testroutinen\Download with Progress\Oskars neuer Code.au3"

    @@ Debug(3) : $sFile = 0

    >Error code: 13

    >Exit code: 0 Time: 0.4261


    Und mit Bitnuggers Code erhalte ich folgende Ausgabe in der Console:

    >"D:\Programme\AutoIt3\SciTE-AutoIt3Installer\..\autoit3.exe" /ErrorStdOut "H:\Notebook-Reparatur\Mainboardverwaltung\Testroutinen\Download with Progress\Bitnuggers Code.au3"

    > ohne_InternetSetOptionsW()

    + ohne_selfhtml812.zip wurde erfolgreich gespeichert

    > ohne_InternetSetOptionsW()

    ! Fehler beim Herunterladen von ohne_Lichteffekte_500t.jpg

    + CONNECT_TIMEOUT wurde geändert!

    + RECEIVE_TIMEOUT wurde geändert!

    > mit_InternetSetOptionsW()

    + mit_selfhtml812.zip wurde erfolgreich gespeichert

    > mit_InternetSetOptionsW()

    ! Fehler beim Herunterladen von mit_Lichteffekte_500t.jpg

    >Exit code: 0 Time: 23.72


    Kann es eventuell an Windows XP liegen?

    Zitat von autoiter

    Vielleicht machst du einen eigenen Thread auf? ;)

    Es liegt mir natürlich fern, Oscars Thread zu kapern, aber die Probleme begannen beim Testen des Codes aus seinem Startposting; ungeachtet dessen, dass sich später zeigte, dass sogar auf bloßes InetGet() reduzierter Code die gleichen Probleme macht.

    Wenn InetGet nicht unter allen Umständen funktioniert, dann betrifft das auch Oscars Code. Von daher halte ich es nicht für sinnvoll, einen eigenen Thread zu eröffnen.

    Oscars Code finde ich große Klasse, eben weil der alle möglichen Fehler abfängt.

    Bei mir tritt ein bisher nicht berücksichtigter Fehler auf, der zwar sauber abgefangen wird, aber halt dazu führt, dass die gewünschte Datei nicht herunter geladen wird.

  • _DownloadWithProgress

    • Code-Jack
    • 18. November 2018 um 07:36

    Danke für den Hinweis, autoiter, aber das hilft nicht.

    Ich habe auch keine großen Dateien beim Wickel, sondern es scheitert schon an kleinen Bildern (paar kB).

    Davon abgesehen, klappt ja auch schon das simple Ermitteln der Dateigröße nicht, mittels InetGetSize.

    Diese URL funzt:

    Global $sURL = 'http://SunSITE.Informatik.RWTH-Aachen.DE/ftp/pub/packages/SELFHTML/selfhtml812.zip'

    Und diese funzt nicht:

    Global $sURL = 'https://www.edv-dompteur.de/image/mini/Lichteffekte_500t.jpg'

    Der Code des geschätzten Bitnuggers, aus dem von Dir erwähnten Thread, ändert daran nichts.

    Es nützt auch nichts, InetRead anstelle von InetGet zu verwenden (wäre ja auch sonderbar).

    Bis jetzt habe ich den Eindruck, dass InetGet immer dann scheitert, wenn InetGetSize ebenfalls scheitert, also die Dateigröße nicht ermitteln kann.

    Die Datei existiert jedenfalls auf dem Server und ist per Browser problemlos downloadbar, wenn man die URL ins Adressfeld kopiert.

    Über die Konsole kommen nur die Error-Flags der jeweiligen Befehle (die die Hilfedatei leider nicht näher aufschlüsselt); am Code selbst wird nichts bemängelt.

  • _DownloadWithProgress

    • Code-Jack
    • 18. November 2018 um 05:01

    Ein großartiges Tool und so schön "mundfertig"! :thumbup:

    Dummerweise erhalte ich häufig den Fehler Nr. 6 - "Dateigröße konnte nicht ermittelt werden".

    Das passiert u. a. bei Bildern von Wikipedia, aber leider (und das ist übel) auch bei Dateien von meinem eigenen Webauftritt, die man dort per Browser, ohne Login etc., problemlos direkt herunterladen kann.

    Es passiert sogar bei harmlosen Bildern, die von meinen (im Editor handgestrickten, ultraschlichten) HTML-Seiten ohne jedweden Kunstgriff eingebunden werden.
    Es hakt auch bei ganz unkomplizierten Links, ohne Bindestriche, Underlines, Sonderzeichen etc.

    Muss der Server irgendwie speziell konfiguriert sein, damit die Dateigröße ermittelt werden kann?

    In der Hilfe zu InetGetSize steht:

    "Not all servers will correctly give the file size, especially when using a proxy server."

    Natürlich bin ich mir keiner Schuld bewusst, meinen Server irgendwie schräg konfiguriert zu haben. :/
    Ich könnte auf die ProgressBar verzichten, wenn die Dateigröße nicht ermittelt werden kann, hauptsache die Datei wird herunter geladen. Darum probierte ich mal, unter Verzicht auf Oskars Tool, nacktes IneGet() zum Downloaden. Ging bei den "problembehafteten" Dateien aber auch nicht ...

    Warum geht es per Browser, jedoch nicht per InetGet? Und was kann man da tun?

  • Alinas_SQLite_BuchVw

    • Code-Jack
    • 18. November 2018 um 02:54

    Verbesserungsvorschlag zum Programm aus dem Startposting:

    Der praktische Nutzwert des Programms lässt sich enorm steigern, durch das Hinzufügen eines einzigen Prozentzeichens an richtiger Stelle:

    Code
    ;Vorher:
    _ListViewFill("SELECT ROWID,* From Buchverwaltung WHERE " & GUICtrlRead($cboSearch) & " LIKE '" & GUICtrlRead($iptSearch) & "';")
    
    ;Nachher
    _ListViewFill("SELECT ROWID,* From Buchverwaltung WHERE " & GUICtrlRead($cboSearch) & " LIKE '" & GUICtrlRead($iptSearch) & "%';")

    Der Lohn der Mühe:

    Suchbegriffe können fortan abgekürzt werden.

    Der Suchbegriff "Har", oder auch nur "Ha" etc., würde sämtliche Harry-Potter Bücher finden. :)

    Man muss den Titel, Autorennamen etc. also nicht mehr exakt kennen, bzw. korrekt erraten. :Glaskugel:


    Und wenn wir schon dabei sind, gleich noch eine weitere, winzige Anregung:

    Beim Kreieren der ListView würde ich vorschlagen, $LVS_EX_HEADERDRAGDROP mit anzugeben, damit der User die Spalten per Maus anders anordnen kann.

    Was das soll?

    Nun, um es wieder am Beispiel von Harry-Potter zu erklären:

    Nicht nur, dass es davon bekanntlich sieben Bände gibt - es gibt sie alle gleich mehrfach und zu (deutlich!) verschiedenem Preis (zumindest die englischen Ausgaben):

    Gebunden, Taschenbuch, Sammler-Edition mit Kunstdruck ...

    Da kommt also eine ziemlich fette und verwirrende Trefferliste zusammen, weswegen es für den Bediener Sinn macht, die Preisspalte mal schnell neben die Titelspalte ziehen zu können, für einen einfacheren Vergleich.

  • Forenupdate - November 2018 - Probleme / Anregungen / Feedback - Sammelthread

    • Code-Jack
    • 18. November 2018 um 02:23

    Die Suchfunktion ist im Eimer.

    Zu "SQLite" gibt es immerhin einen Treffer - scheint hier kein besonders üppiges Forum zu sein ... ;)

    Zu diversen anderen Begriffen erhalte ich entweder Null, oder wiederum nur einen einzigen Treffer.

  • Editbox nachträglich in TabControl verschieben

    • Code-Jack
    • 8. November 2018 um 21:19

    Bitnugger: Hmm, also dieses GUIRegisterMsg ist laut Hilfe ja ziemlich mit Vorsicht zu genießen.

    Es interferiert mit MsgBox und andere Späße.

    Ich poste mal meinen eigenen Code, der bei mir (Win XP) bestens funktioniert.

    Ignoriere bitte, dass ich hier nicht alle Eigenschaften des Edits sichereund neu setze. Es ist nur ein Minimalbeispiel.

    Macht dieser Code Probleme, unter höheren Windows-Versionen?

    AutoIt
    #include <GUIConstantsEx.au3>
    #include <GuiTab.au3>
    #include <GuiEdit.au3>
    #include <GuiStatusBar.au3>
    #include <WindowsConstants.au3>
    #include <MsgBoxConstants.au3>
    
    Global $hGUIParent1 = GUICreate("Parent1", 600, 400)
    Global $idTabCtrl
    Global $idTabItem1
    Global $idTabItem2
    
    Example()
    GUIDelete($hGUIParent1)
    
    Func Example()
    
        Local $InhaltInputBox3
        Local $idInput3
    
        ;--- Buttons kreieren -------------------------------------------------------------------\
        $Button1 = GUICtrlCreateButton("Move Inputbox in Tab 2", 350, 10, 200, 50)
        $Button2 = GUICtrlCreateButton("Move Inputbox in Tab 1", 350, 70, 200, 50)
        $Button3 = GUICtrlCreateButton("Kreiere Input außerhalb der Tabs", 350, 130, 200, 50)
        ;--- Buttons kreieren -------------------------------------------------------------------/
    
        ;--- TabControl kreieren, inklusive eines darin befindlichen Inputfeldes ----------------\
        $idTabCtrl = GUICtrlCreateTab(10, 40, 300, 300)
        $idTabItem1 = GUICtrlCreateTabItem("tab1")
        Local $idInput2 = GUICtrlCreateInput("Ich möchte moven!", 50, 150, 200, 30)
        $idTabItem2 = GUICtrlCreateTabItem("tab2")
        GUICtrlCreateTabItem("")                        ;Die Tab-Definition abschließen
        ;--- TabControl kreieren, inklusive eines darin befindlichen Inputfeldes ----------------/
    
    
        GUISetState(@SW_SHOW)
    
        ;--- Programmschleife -------------------------------------------------------------------\
        While 1
          Switch GUIGetMsg()
          Case $GUI_EVENT_CLOSE                            ;# Fenster wurde geschlossen, nun raus hier!
               ExitLoop
    
          Case $Button2                                    ;# Editfeld in Tab Nr. 1 verschieben.
             $idInput2 = _MoveToTab2($idInput2, 1)
    
          Case $Button1                                    ;# Editfeld in Tab Nr. 2 verschieben.
             $idInput2 = _MoveToTab2($idInput2, 2)
    
          Case $Button3                                    ;# Neues Editfeld kreieren, außerhalb des Tabcontrols.
             GUICtrlCreateTabItem("")                      ;# TabControl "deselektieren", um fortan außerhalb dessen neue GUI-Elemente kreieren zu können.
             _GUICtrlTab_DeselectAll($hGUIParent1, False)
             GUISwitch($hGUIParent1)                       ;# Das Ziel der kommenden Aktion definieren.
             $idInput3 = GUICtrlCreateInput("Ich soll nicht in Tab!", 350, 250, 200, 30)
             ;ConsoleWrite($idInput3 & @crlf)
          EndSwitch
        WEnd
        ;--- Programmschleife -------------------------------------------------------------------/
    
    EndFunc   ;==>Example
    ;############################################################
    Func _MoveToTab2($id, $iTabNr)
       Local $idNeueID
       Local $InhaltInputBox = GUICtrlRead($id)                             ;# Inhalt des gleich temporär zu löschenden Inputfeldes auslesen.
    ;   Local $aPosInput = ControlGetPos($hGUIParent1, 'Parent1', $id)
       Local $aPosInput = ControlGetPos($hGUIParent1, "[ACTIVE]", $id)      ;# Postion des Inputfeldes auslesen.
       Local $StatusInputBox = GUICtrlGetState($id)                         ;# Status des Inputfeldes auslesden.
       Local $idTmp
    
       GUICtrlDelete($id)                                       ;# Löscht temporär das Editefeld, das eigentlich verschoben werden soll.
       If $iTabNr = 1 Then
         $idTmp = GUISwitch($hGUIParent1, $idTabItem1)          ;# Tab Nr. 2 "answitchen"
       ElseIf $iTabNr = 2 then
         $idTmp = GUISwitch($hGUIParent1, $idTabItem2)          ;# Tab Nr 1 "answitchen"
       EndIf
    
       $idNeueID = GUICtrlCreateInput($InhaltInputBox, 1, 1)    ;# Kreiert das zuvor temporär gelöschte Editfeld neu, unter identischer ID.
       GUICtrlSetPos($idNeueID, $aPosInput[0], $aPosInput[1])   ;# Recycelt die Position des Inputfeldes.
       GUICtrlSetState($idNeueID, $StatusInputBox)              ;# Recycelt den Status des Inputfeldes.
    
       _GUICtrlTab_SetCurSel($idTabCtrl, $iTabNr - 1)                       ;# Selektiert den Ziel-Tab
       ;_GUICtrlTab_ActivateTab($idTabCtrl, $iTabNr - 1)                    ;# Ebenfalls funktionierende Alternative zu _GUICtrlTab_SetCurSel()
    
       Return($idNeueID)
    EndFunc  ;==> MoveToTab2
    Alles anzeigen
  • Editbox nachträglich in TabControl verschieben

    • Code-Jack
    • 8. November 2018 um 15:08
    Zitat von alpines

    Falls dich sowas wirklich stört kannst du dazu gerne in den entsprechenden Hilfe-Threads was dazu posten, wir sorgen schon dafür, dass in den nächsten Hilfeversionen (auch die aktuelle Online-Hilfe) dann geupdatet wird, damit solche Missverständnisse in Zukunft nicht mehr auftreten.

    Danke alpines!

    Und ja, Du hast Recht, es ist wirklich eine Kunst, eine "für Dumme" taugliche Anleitung zu schreiben. Denn dem Aotor, der eine Anleitung schreibt, sind die "trivialen" Zusammenhänge ja sonnenklar. Der kommt kaum auf die Idee, dabei Probleme zu erwarten.

    Ich werde dann künftig in den Hilfe-Threads meine Vorschläge einreichen.


    Zitat von Bitnugger

    Ich habe dein Script aus Post #8 mal ein wenig geändert und erweitert, damit bei der neu erstellten InputBox auch die Styles und ExStyles erhalten bleiben.

    Danke Bitnugger!

    Ich hatte es zuletzt für mich bereits so umgesetzt, dass die Styles etc. erhalten bleiben und alles fehlerfrei funzt.

    Mein Codebeispiel war ja speziell fürs Forum auf das Minimum kastriert.

    Ich teste hier zunächst nur unter Windows XP. Da läuft mein (voller) Code einwandfrei.

    Die Tests unter höheren Windows-Versionen kommen bei mir erst später an die Reihe.

    Gut dass Du darauf aufmerksam machst, dass da eventuell Probleme zu erwarten sind!

  • Editbox nachträglich in TabControl verschieben

    • Code-Jack
    • 8. November 2018 um 01:22

    Ja, ich habe die Sachen ja gelesen. Habe viel RTFM gemacht.

    Aber ich finde es noch immer missverständlich. Denn ich hatte das TabItem ja brav geschlossen ... halt nachdem die Tabelle kreiert wurde ... :)

    # Don't forget to close tabitem definition GUICtrlCreateTabItem("")

    - Hatte ich ja artig gemacht. Jedenfalls so, wie ich diesen Text verstanden hatte; also nach der "tabitem definition".

    # Es darf nicht vergessen werden, das tabitem mit der Funktion GUICtrlCreateTabItem("") zu schließen.

    - War ja - wie ich dachte - längst gemacht, gleich nach dem Kreieren der Tabelle. Sache für abgehakt befunden!

    # It is important to close the tab structure by creating a final tabitem control with a null text - GUICtrlCreateTabItem("").

    - Aber sowatt von, hatte ich die "tab structure" geschlossen! Gleich nach dem Kreieren! Abgehakt!

    # Es ist wichtig die Tab-Struktur mit einem TabItem-Control mit leerem Text abzuschließen - GUICtrlCreateTabItem("")

    - Hey, ich bin hier der König des "Tab-Struktur-Schließens"! (Nach dem Kreieren der Tabelle ...)

    Alpines, ich hatte wirklich brav RTFM gemacht. Aber ich finde die Erklärungen in den Hilfedateien noch immer nicht klar genug.

    All diese diversen Erwähnungen von "structure" und "defination" hatte ich überhaupt nicht mit der Verwendung von GUISwitch in Verbindung gebracht, sondern (natürlich?) mit dem Erstellen der Tabelle.

    Beim Erstellen hat man es mit "Struktur" zu tun und muss sonstwas "definieren". Aber doch nicht beim bloßen Switchen ...

    Wenn ich bloß zu doof war und das einsehe, dann gebe ich das auch zu.

    Aber hier finde ich die Hilfedateien wirklich reichlich supotimal. Die Texte sind nicht präzise und unmissverständlich formuliert, sondern sie sind so oder so interpretierbar. Aber kaum korrekt interpretierbar, ohne sich das schön zu reden.

    Würde dort nicht so viel von "defination" und "structure" stehen, sondern klar und deutlich, dass man nach der Anwendung von _GUISwitch() wieder zum Fenster zurück "switchen" kann, indem man GUICtrlCreateTabItem("") anwendet, dann hätte gar kein Missverständnis entstehen können - das mich hier wohl gute 2-3 Stunden gekostet hatte.

    Ich schreibe das ja nicht, um zu nörgeln, sondern ich bedaure es, wenn AutoIt wegen solcher Sachen ein unverdientes Schattendasein fristet.

    Es sind diese scheinbaren Kleinigkeiten, die massiv Zeit kosten.

    Der Kopf ist voller guter Ideen, die nach Umsetzung schreien, aber dauernd klemmt es - woraufhin dann jedes Mal eine ziemliche Orgie von RTFM, Googelei und Forendurchforstung folgt.

    - Womöglich weiterhin gefolgt, von einer kleinlauten Frage hier im Forum, nachdem alles RTFM und alle Codetests nicht fruchteten.

    Ihr macht Euch hier im Forum die lobenswerte Mühe, die englische Hilfe auf Deutsch zu übersetzen. Und das, obwohl Ihr selbst das Resultat sicher längst nicht mehr benötigt. Ihr tut das also eher aus Altruismus, um Einsteigern zu helfen. Daumen hoch dafür!

    Jetzt komme ich (forgeschrittener Einsteiger, "Gelbgurt") und stoße Euch mit der Nase auf Stellen, wo es für Neulinge echt klemmen kann.

    Betrachtet meine Ausführungen daher bitte als konstruktive Hinweise, nicht als Nörgelei.

  • Editbox nachträglich in TabControl verschieben

    • Code-Jack
    • 7. November 2018 um 21:49

    Ja alpines, genau das sind die vielen Kleinigkeiten, die einen Einsteiger ausbremsen.

    Du hast es schon in der ersten Antwort erwähnt und ich hatte mir natürlich auch die englische Hilfedatei zur Brust genommen und bei GUISwitch nachgeschaut.

    Aus den für meinen Geschmack etwas spärlichen Informationen zu GUISwitch ging für mich aber nicht hervor, dass man den Befehl, um den es geht, noch ein weiteres Mal im Code platzieren muss.

    Ich dachte, er müsste lediglich nach dem Kreieren der Tabelle angewendet werden und das war bei mir ja eh schon der Fall; hielt den Punkt daher für abgehakt.

    Du hattest den Hilfe-Eintrag zu GUICtrlCreateTabItem verlinkt. Dort ist es tatsächlich explizit für GUISwitch erwähnt, dass man die Struktur "once again" abschließen soll.

    Dieser Hinweis wäre in der Hilfedatei meiner Meinung nach deutlich besser im Eintrag zu GUISwitch aufgehoben.

    Ich finde den Hilfe-Eintrag zu GUISwitch nicht nur spärlich, sondern sogar missverständlich.

    Dabei - und das ärgert mich im Nachhinein - ist GUICtrlCreateTabItem("") dort im Codebeispiel tatsächlich doppelt vorhanden.

    Das fällt einem nur nicht ins Auge, wenn man es gar nicht auf dem Plan hat, dass dieser Befehl von Bedeutung ist, für das was man vorhat.

    Dem Codebeispiel fehlt nämlich genau das, worum es mir zuletzt ging: Nach dem Switchen wieder außerhalb des TabControls weiter zu machen und neue GUI-Elemente dort außerhalb zu platzieren.

    Das sind Fallstricke, die Ihr erfahrenen Superprogrammierer vermutlich schon gar nicht mehr wahrnehmt.

    Aber einem Einsteiger macht es halt das Leben schwer.


    Für viel wichtiger, als die bloße Übersetzung der Hilfedatei auf Deutsch, würde ich daher eine Ausschmückung halten.

    Also ausführlichere Texte und brauchbarere Codebeispiele, die wirklich vollumfanglich das zeigen, was von Bedeutung ist.

  • Datenbank dezentral erweitern [gelöst]

    • Code-Jack
    • 7. November 2018 um 21:10
    Zitat von chesstiger

    Du solltest deinen Primary Key aber nicht als TEXT definieren, sondern wenn möglich als VARCHAR(n). Zumindest MySQL ist bei einem Index mit VARCHAR wesentlich performanter und deine GUIDs sind ja eh immer gleichlang.

    Habe ich erfolgreich umgesetzt, danke für den Hinweis!

    Einen Geschwindigkeitsunterschied bemerke ich bei 1300 Datensätzen mit 32 Spalten noch nicht. Aber mehr als bloßes Schreiben/Lesen aus/in die Datenbank läuft bei mir eh noch nicht, bezüglich SQL-Kommandos.

    Erstaunlicherweise gibt es bei sqlitetutorial.net kaum Treffer zum Suchstring "VCHAR".

    Die Artikel, die sich dort mit dem Kreieren von Tabellen, mit dem Primary Key und mit den Datentypen befassen, schweigen sich darüber allesamt sogar völlig aus. Und dort hatte ich zuerst geguckt, was so geht.

    Wieder etwas schlauer geworden!

  • Alinas_SQLite_BuchVw

    • Code-Jack
    • 7. November 2018 um 20:54
    Zitat von autoiter

    Bulletproof finde ich es aber auch noch nicht. Du solltest am besten allgemein die Funktion _SQLite_Escape benutzen (dann sparst du es dir auch eventuelle Steuerzeichen im Text escapen zu müssen)

    Guter Hinweis, Danke!

    Die Umsetzung war steiniger, als erwartet, im Nachhinein betrachtet aber doch simpel.

    Läuft jetzt!

    Aus Einsteigersicht schon fies, wenn Beispiele aus der Hilfe nicht direkt lauffähig sind ...

    SQLite_Escape lieferte bei mir ohne Fehlermeldung(!) nur einen Leerstring zurück.

    Per:

    ConsoleWrite("_SQLite_LibVersion=" & _SQLite_LibVersion() & @CRLF)

    konnte ich den Übeltäter aber aufspüren. Beim Includen dieser leidigen SQL Lib hatte etwas nicht geklappt.

    Zwar hatte ich die Lib im Scriptverzeichnis, aber man muss es AutoIt schon explizit sagen, dass es die Lib dort auch suchen soll (Augenroll). Ich war zwar der festen Meinung, die hätte ich darüber hinaus schon lange auch im normalen Include-Verzeichnis von AutoIt liegen und sie wäre somit sogar doppelt vorhanden, dem war aber nicht so.

    So toll ich AutoIt auch finde (ich liebe es!), so sind es doch immer wieder ganze Massen solcher Kleinigkeiten, an denen es stundenlang klemmt.

    Die Hilfedatei könnte für meinen Geschmack dreimal so umfangreich sein.

    Ohne die 1000 Codebeispiele aus diesem großartigen Forum wäre ich wohl nie auf die Idee gekommen, dass beim Includen der Lib etwas schief gegangen sein könnte.

    Die große Lehre die ich daraus ziehe: Viel mehr Fehlerabfangroutinen spendieren!!!

    Und Du rennst bei mir offene Türen ein, wenn Du von "Bulletproof" sprichst!

    Das ist nämlich genau das, was ich im Startposting zum Ausdruck bringen wollte: Code sollte im Idealfall "idiotensicher" portierbar sein, statt bloß den momentanen Zweck zu erfüllen.

    Ich bin selbst noch gar nicht in der Lage, diesem Ideal voll zu entsprechen, aber das ist meine eigene Zielvorgabe. Und Dein Hinweis hat mich diesem Ziel wieder ein Stück näher gebracht.

    Danke!

  • Editbox nachträglich in TabControl verschieben

    • Code-Jack
    • 7. November 2018 um 05:25

    Ergänzend möchte ich noch sagen, dass derjenige Tab, in den man zuletzt ein GUI-Element verschoben hatte, irgendwie "klebrig" ist.

    Erstellt man nämlich im Anschluss ein neues Editfeld etc., so landet dieses wiederum im Tab, auch wenn man es doch eigentlich im Hauptfenster haben wollte.

    Per GUISwitch() lässt sich das auch nicht abstellen.

    Was hingegen Abhilfe schafft:

    Zuletzt diese Zeile ausführen:

    GUICtrlCreateTabItem("")

    - Die hat man zwar typischerweise schon an anderer Stelle stehen, nämlich am Ende des Codes, der das TabControl kreierte, aber man kann die Zeile auch mehrfach im Quelltest einfügen, nämlich überall da, wo man nach dieser GUISwitcherei das TabControl wieder "deselektieren" möchte.

    Vielleicht hilft der Tipp ja mal jemandem.

  • Datenbank dezentral erweitern [gelöst]

    • Code-Jack
    • 7. November 2018 um 05:12

    Irgendwie kann ich Dir nicht folgen, autoiter.

    Wieso würde sich in der IMDB etwas verschieben, wenn dort ein Film gelöscht wird?

    Durch dieses lebenslange GUID-Fingeprinting, eines jeden einzelnen Datensatzes, ist das doch ausgeschlossen!?!

    In meinem eigenen Fall soll - wie ja schon ausgiebig erläutert - jeder Datensatz eine ewig gültige und garantiert eindeutige ID bekommen.

    Da soll sich nie etwas verändern. Und niemals würde es Auswirkungen auf andere Datensätze haben, wenn dazwischen mal einer gelöscht wird.

    Jeder Datensatz erhält bei mir aber auch zusätzlich eine editierbare ID.

    Die ist analog zu einer Bestellnummer zu sehen. Die kann man durchaus ändern, wird es aber nur höchst selten tun.

    Dank der GUID kann ich es nun sogar zulassen, dass mehrere Datensätze die selbe "Bestellnummer" haben, ohne dass Chaos auftritt. Das ist zwar nur selten sinnvoll, aber es kann sinnvoll sein.

    Ich sage nur: "USB-Stick, 8GB, NoName".

    - Da kann man unter der selben Bestellnummer alles verramschen, was man sonstwoher aus China kartonweise eingekauft hat.

    Für die Nachbestellung beim Lieferanten sind es aber eben doch unterschiedliche Sticks (und Datensätze).

    Die GUID regelt das souverän.


    Also ich muss schon sagen: All Eure Antworten hier im Thread waren gut, aber insbesondere der superknappe Hinweis von Bitnugger war echt der Bringer, der mir total die Augen geöffnet hat!

    Inzwischen habe ich mein Programm vollständig auf GUID umgestellt und alles funzt.

    Jetzt kommen noch die Routinen, die die Tauscherei der Userdaten unterstützen, dann kann langsam der Testbetrieb mit einem zweiten Anwender starten.

  • Alinas_SQLite_BuchVw

    • Code-Jack
    • 7. November 2018 um 04:46

    Etwas verlegen bin ich geneigt zu behaupten, die Codevorlage des geschätzten RR04 enthält einen Bug, der sich bloß nicht bemerkbar macht.

    Ich habe ja eine Menge von dieser Vorlage abgekupfert und immer mehr erweitert. Und niemals ist mir dieser Bug aufgefallen, weil er halt nie in Erscheinung trat.

    Doch nachdem ich nun in meinem Programm die SQLite-Tabelle nicht mehr mit INTEGER AUTOINCREMENT für die ID kreiere, sondern dort eine GUID als TEXT (statt Integer) verwende ...

    siehe hier: Datenbank dezentral erweitern [gelöst]

    ... trat der Bug plötzlich in Erscheinung. Sogar gleich in zwei Routinen.

    Nun ja, bei mir selbst beseitigte ich den.

    Interessiert kramte ich den alten Code von RR04 wieder hervorund tatsächlich ist er dort schon vorhanden.

    Hier die Stelle um die es geht:

    AutoIt
    Func _DsUpdate()
        _SQLite_Exec(-1, "UPDATE Buchverwaltung SET  Titel = '" & GUICtrlRead($aCtrlInput[1]) & "', Autor = '" _
                 & GUICtrlRead($aCtrlInput[2]) & "', Verlag = '" & GUICtrlRead($aCtrlInput[3]) & "', Genre = '" _
                 & GUICtrlRead($aCtrlInput[4]) & "', Einband = '" & GUICtrlRead($aCtrlInput[5]) & "', ISBN = '" _
                 & GUICtrlRead($aCtrlInput[6]) & "', Preis = '" & GUICtrlRead($aCtrlInput[7]) & "', Erscheinungsdatum = '" _
                 & GUICtrlRead($aCtrlInput[8]) & "', Seiten = '" & GUICtrlRead($aCtrlInput[9]) & "', Lagerplatz = '" _
                 & GUICtrlRead($aCtrlInput[10]) & "', Serie = '" & GUICtrlRead($aCtrlInput[11]) & "', Lfd_Nr = '" _
                 & GUICtrlRead($aCtrlInput[12]) & "', Ausgeliehen_an = '" & GUICtrlRead($aCtrlInput[13]) & "', Ausgeliehen_am = '" _
                 & GUICtrlRead($aCtrlInput[14]) & "', Ausgeliehen_bis = '" & GUICtrlRead($aCtrlInput[15]) & "', Bestellt = '" _
                 & GUICtrlRead($aCtrlInput[16]) & "', Gelesen = '" & GUICtrlRead($aCtrlInput[17]) & "', Note = '" _
                 & GUICtrlRead($aCtrlInput[18]) & "', Zusatz = '" & GUICtrlRead($aCtrlInput[19]) & "', Information = '" _
                 & GUICtrlRead($aCtrlInput[20]) & "' WHERE ID = " & GUICtrlRead($aCtrlInput[0]) & ";")
    EndFunc   ;==>_DsUpdate
    Alles anzeigen

    Meines bescheidenen Erachtens fehlen hier zwei Hochkommas.

    Die letzte Zeile müsste IMHO so aussehen:

    AutoIt
    & GUICtrlRead($aCtrlInput[20]) & "' WHERE ID = '" & GUICtrlRead($aCtrlInput[0]) & "';")

    Wie gesagt: Der (von mir so betrachtete) Bug machte sich bisher nie bemerkbar. Vermutlich weil die als Integer erzeugte ID von SQLite als Zahl verdaut wurde und daher keine Einfassung in Hochkommas benötigte.

    Ich hingegen, verwende nun neuerdings keinen Integer mehr als ID, sondern einen String. Und dann klemmt es, ohne die Einfassung.

    Weil hier ja doch viele Codebeispiele mit SQLite im Forum zu finden sind (was vermuten lässt, dass die Macke verbreiteter ist) und weil mir die Vorlage von RR04 so gut gefiel, wollte ich mal dezent darauf hingewiesen haben.

    Da kann man sich in unübersichtlicher gestalteten Vorlagen, als dieser hier, ja sonst 'nen Wolf deduggen, als SQL-Anfänger.

    Konzeptionelles:

    Ich stricke mein Programm übrigens so, dass am Ende nur genau eine einzige Routine Daten aus der SQLite-Datenbank holt.

    Und nur genau eine einzige Routine schreibt Daten hinein.

    Alle sonstigen Routinen, die irgendwie Daten aus/in SQLite holen/schreiben wollen, tun das nicht mehr direkt, sondern über eine zwischengeschaltete Func, die den jeweiligen Befehl auf die Schreib- bzw. Leseroutine leitet.

    Darin sehe ich zwei Vorteile:

    Erstens erpart man sich massig Fehlerquellen. Dieser SQL-Kram ist ja echt so ein Ding für sich.

    Zweitens kann man blitzschnell völlig andere Datenquellen implementieren.

    Wenn also eines Tages statt SQLite eine ganz andere Datenstruktur gefordert wird, dann braucht man nur eine neue Schreib- und eine neue Leseroutine zu stricken und die Umleitung halt ... umleiten.

    Man muss dann also nicht umständlich an gefühlt 1000 Stellen im Programm Hand anlegen, wo irgendwas mit SQL passiert.


    Noch eine konzeptionelle Sache, nur als Anregung:

    Wenn ein Datensatz in der Maske editiert wird, dann schreibe ich die Daten im Anschluss zuerst in die SQLite-Datenbank. Anschließend lese ich sie von dort wieder aus und aktualisiere mit den daraus ausgelesenen Daten (die zunächstin ein Array wandern) die ListView, oder was auch immer.

    Darin sehe ich folgende Vorteile:

    Erstens fällt es sofort ins Auge, wenn bei den SQL-Aktionen etwas (ohne Fehlermeldung) schief gegangen sein sollte.

    Zweitens verringert sich die Anzahl an Routinen, die irgendwie eigenmächtig Daten lesen, schreiben und kreuz und quer untereinander hin & her konvertieren.

    Also statt aus den Editfeldern auszulesen und damit die ListView zu füllen und dann irgendwie in die Datenbank ... ist der Datenfluss bei mir irgendwie klarer strukturiert.

    Die Quelle für alles ist immer die Datenbank!

    Und die wird stets zuerst schreibend aktualisiert. Erst von da aus werden dann erst Edits, Listviews etc. befüllt/aktualisiert - stets direkt aus der Datenbank kommend.

    (Mit einem dazwischen geschalteten Array, sei der Vollständigkeit halber noch erwähnt).

    Nur eine einzige Routine schreibt in die Datenbank.

    Und nur eine einzige Routine holt Daten dort heraus.

    Alles sonstige läuft über ein dazwischen geschaltetes Array.

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™