[vb6] Zrozumienie kodu


(Grzeniux) #1

Witam,


(floyd) #2

W każdej lini są dwa wyrazy odzielone spacją np.

haslo1 text1

haslo2 text2

haslo3 text3

Gdy uruchamiamy program tworzona jest tablica ReDim ArrayPassword(0) w której będą zapisywane elementy tablicy. Tablica musiala by wcześniej zadeklarowana: Dim ArrayPassword() As String

Znajdujemy wolny numer pliku do odczytu: FileIn = FreeFile

Otwieramy plik do odczytu: Open App.Path & “\plik.txt” For Input As #FileIn

W pętli

Do While Not EOF(FileIn)

loop

czyli do końca pliku odczytumem pojedyńcze linie pliku instrukcją:

Input #FileIn, inputdata

i zapisujemy do utworzonej tablicy:

ArrayPassword(UBound(ArrayPassword)) = inputdata

jednocześnie  po wczytaniu każdej linii zmieniany jest rozmiar tablicy:

ReDim Preserve ArrayPassword(UBound(ArrayPassword) + 1)

lbount  zwraca najniższy możliwy indeks tablicy

ubount  zwraca najwyższy możliwy indeks tablicy

Po wykonaniu pętli do while jak w podanym przykładzie tablica przyjmie wartości:

ArrayPassword(1)=“haslo1 text1”

ArrayPassword(2)=“haslo2 text2”

ArrayPassword(3)=“haslo3 text3”

i nastąpi zamknięcie pliku do odczytu:Close #FileIn

Po kliknięciu na przycisk command1 sprawdzamy czy pierwsze wyrazy tablicy są wpisane w oknie text2.text i jeżeli tak, to w oknie text1.text wpisywany jest drugi wyraz tablicy.

W tym celu tworzymy pętlę:

For ArrPasswordIdx = LBound(ArrayPassword) + 1 To UBound(ArrayPassword)

next

W omawianym przykładzie będzie to pętla od 1 do 3 bo LBound(ArrayPassword)=0, a UBound(ArrayPassword)=3

W pętli przy kazdym jej obiegu tworzona jest nowa tablica o nazwie: ArrayPWLine przy pomocy instrukcji Split, elementami rozdzielającymi elementy tablicy jest znak " "

ArrayPWLine = Split(ArrayPassword(ArrPasswordIdx), " ")

jeżeli pierwszy element tablicy będzie wyrazem z okna text2.text to do okna text1.text wpisany zostanie drugi element tablicy.

co jest realizowane w liniach:

If ArrayPWLine(0) = Text2.Text Then

Text1.Text = ArrayPWLine(1)

Found = True

End If

Jeżeli zmienna Found przyjmie wartość true, to znaczy że zadanie zostało wykonane poprawnie w przeciwnym przypadku zmienna found będzie miała wartość false.

oczywiście taki programik można napisać na wiele sposobów np. z użyciem jednej tablicy:

Option Explicit
Dim ArrayPWLine() As String

Private Sub Form_Load()
Dim FileIn As Integer
Dim inputdata As String, ZnakKoncaLinii As String
FileIn = FreeFile:ZnakKoncaLinii = Chr(13) + Chr(10)
On Error GoTo Error_Laden
Open App.Path & "\plik.txt" For Input As #FileIn
inputdata = input$(LOF(FileIn), 1)
ArrayPWLine = Split(inputdata, ZnakKoncaLinii)
Close #FileIn
Exit Sub
Error_Laden:
Close #FileIn: MsgBox ("Error loading !")
End Sub
 
Private Sub Command1_Click()
Dim ArrPasswordIdx As Integer, i as integer
Dim Found As Boolean
For ArrPasswordIdx = LBound(ArrayPWLine) To UBound(ArrayPWLine) - 1
i = InStr(ArrayPWLine(ArrPasswordIdx), " ")
If Left(ArrayPWLine(ArrPasswordIdx),i - 1) = Text2.Text Then
Text1.Text = Mid(ArrayPWLine(ArrPasswordIdx),i + 1)
Found = True: Exit For
End If
Next
If Found = False Then
Text1.Text = "": MsgBox "Not a valid name"
End If
End Sub

(Grzeniux) #3

“floyd” dziękuje za obszerną odpowiedź sporo mi to ułatwiło. A jeszcze pytanie czy istenieje możliwośc ograniczenia ilości znaków jakie zostaną wrzucone z tablicy?? Powiedzmy w tablicy drugi wyraz ma ponad 20 znaków a ja potrzebuje tylko 15, w jaki sposó zrobić takie ograniczenie?? I czy w kodzie mozną dodać jeszcze 3 warunek, czyli jeżeli pierwszy element tablicy będzie wyrazem z okna text2.text to do okna text1.text wpisany zostanie drugi element tablicy a do okna text3.text zostanie dodany 3 element talicy który oczywiście będzie odzielał znak " ".

 

Pozdrawiam


(floyd) #4

1)oczywiście, że się da ograniczyć długość zmiennej do np 15 znakow przy pomocy funkcji left.

text=“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”

text=left(text,15)

  1. Też się da.

Jeżeli w każdej linii będą 2 spacje to funkcja split utworzy tabelę 3 wymiarową, czyli będziemy mieli coś takiego:

  • ArrayPWLine = Split(ArrayPassword(ArrPasswordIdx), " ")
  • If ArrayPWLine(0) = Text2.Text Then
  • Text1.Text = ArrayPWLine(1)
  • Text3.Text=ArrayPWLine(2)
  • Found = True
  • End If

(Grzeniux) #5

Czy zapis w timer jaki umieściłem wyżej ma jakieś ograniczenia w odczytywanym pliku?? w notatniku mam prawie 40000 lini z podziałem na 3 tablice które odziela znak"|" , wygląda to mniej więcej tak np:

1234567891234|Zamość|40

4564567890325|Warszawa|50

9875647232834|Bydgoszcz|18

9765345643222|Zakopane|32

i tak do 40000 lini.

 

 przy tak dużej ilości lini po odpaleniu makra wyskakuje kominkat błedu "Run-time error ‘6’ Overflow " program zatrzymuje się na lini kodu “For ArrPasswordIdx = LBound(ArrayPassword) + 1 To UBound(ArrayPassword)” w Timer.


(floyd) #6

Zmień deklarację:

Dim ArrPasswordIdx As Integer na

na

Dim ArrPasswordIdx As long

Integer to liczba całkowita mniejsza od 32768            2^15 = 32768

Jeżeli wstawiona zostanie liczba większa, to właśnie otrzymamy taki komunikat o przekroczeniu zakresu (przepełnieniu).

Po instrukcji

Found = True

można też dodać instrukcję: exit for

nie będzie się wówczas pętla wykonywała do końca.


(Grzeniux) #7
Private Sub Timer1_Timer()
Dim ArrPasswordIdx As Long
Dim ArrayPWLine() As String
Dim Found As Boolean


If s1.Value = 0 Then GoTo koniec:

   Found = False
   For ArrPasswordIdx = LBound(ArrayPassword) + 1 To UBound(ArrayPassword)
      ReDim ArrPwline(0)
      ArrayPWLine = Split(ArrayPassword(ArrPasswordIdx), "|")
      If ArrayPWLine(0) = text2.Text Then
         Text1.Text = ArrayPWLine(1)
         Label4 = ArrayPWLine(2)
         
         Found = True
      End If
   Next
   If Found = False Then
      Text1.Text = ""
      Label4 = ""
    
   End If
koniec:

If c1.Value = 0 Then GoTo k:
Text6.Text = Val(Text7.Text) * Val(Label4)
k:


End Sub

Zmieniłem deklaracje na long i dalej nic, tylko ze teraz w miejscu text1.text pojawia mi się cyfra nie wiem skąd , no i komunikat “run time error 9 subscript out of range” ,przy debugowaniu podświetla się linia Label4 = ArrayPWLine(2) czy coś jeszcze powinienem zadeklarować ??


(floyd) #8

Taki błąd powstaje wtedy jeśli polecamy wpisanie danych które nie istnieją.

Sprawdzanie 40000 linii jest jednak dość kłopotliwe. W tekście każda linia powinna skladać się z trzech wyrazów, no i nie powinno być pustych linni, także na końcu.

Najprościej jest zatosować na początku procedury komendę:

On error resume next

Co oznacza: jeśli błąd skocz do następnej linii.

Polecenia tego należy jednak stosować ostrożnie i w wyjątkowych wypadkach bo wprawdzie nie zostanie pokazany żaden błąd, ale program może działać po prostu źle.

Używasz jak widzę obiektu label4 z cechą caption istnieją jeszcze inne cechy dla tego obiektu.

Poprawnie należało by pisać: label4.caption=ArrayPWLine(2)

No i za dużo tych skokow bezwzględnych: goto koniec goto k

Wygląda to bardzo nie elegancko i powinno się używać takich skoków w wyjątkowych wypadkach.

If c1.Value <> 0 Then

Text6.Text = Val(Text7.Text) * Val(Label4)

endif

goto koniec też łatwo ominąć, ale to już zadanie dla Ciebie. :slight_smile:


(Grzeniux) #9

Poprawiłem tak jak zaporponowałeś wyżej, plik txt ładuje się poprawnie ale w dalszym ciągu nie mogę dojść dlaczego w miejscu text1.text przy odpalaniu makra wskakuje mi cyfra . W tym oknie powino pojawić się dopiero cokolwiek jak w oknie text2.text wprowadze jakąś daną z tablicy pierwszej. Na chwilę obecną użyłem w kodzie że jeśli text2.text jest pusty to ma omijac cały kod i na chwilę obecną jakoś działa :slight_smile:


(floyd) #10

Jeżeli programik działa prawidłowo na jakimś pliku testowym złożonym np. z trzech linijek, to powinien też działać prawidłowo na pliku złożonym z większej liczby linii.

Program będzie działał prawidłowo jeżeli w każdej linii będą dokładnie dwie spacje rozdzielające trzy wyrazy.

Jeżeli w linii będą dwie  lub więcej spacji obok siebie czyli np. "  " , to wynik też nie będzie prawidłowy.

Wielokrotność spacji można usunąć nawet  w notatniku wykorzystując opcję: edycja/zamień i wpisując w oknie ‘znajdź’ dwie spacje, a w oknie ‘zamień na:’ jedną spację. Czasami taką operację trzeba wykonać kilka razy, gdy spacji obok siebie jest więcej.

Jeśli chcesz, to mogę też sprawdzić ten plik, ale musiał byś go gdzieś wrzucić np. tutaj: http://www.sendspace.pl/

albo gdzie indziej.


(Grzeniux) #11

Pliczek z danymi poprawiłem i wydaje się być ok. Utworzyłem teraz drugi plik z kilkoma danymi który jest odczytywany w combobox1. I chciałbym zeby do tego pliku w nowych wierszach dopisywać dodatkowe wartości dodawane za pomocą text1.text, napisałem kawałek kodu ale on tylko nadpisuje cały plik na ten jeden wiersz

Private Sub Command1_Click()


Open App.Path & "\plik.txt" For Output As #1
Print #1, text1
Close #1
End Sub

Czy w VB6 można tworzyć też aplikacje które komunikują się powiedzmy z przeglądarką “IE” i poprzez aplikacje do przeglądarki mogą być wysyłane jakieś dane ,np logowanie do poczty przez przeglądarkę czyli login i hasło.


(floyd) #12

1)Użyj polecenia na dopisywanie do pliku:

Open App.Path & “\plik.txt” For Append As #1

Print #1, Text1.text

jeżeli polecenie  Open App.Path & “\plik.txt” For Append As #1 umieścimy w:

 Private Sub Form_Load()

  Open App.Path & “\plik.txt” For Append As #1

end sub

i nigdzie nie będzie próby jego otwarcia  do innych poleceń lub zmknięcia(close#1), to

przy obsłudze klawisza command1 wystarczy tylko wpisać: Print #1, text1.text.  Takiego dopisywania można też użyć w dowolnym miejscu programu pisząc tylko: print#1,“dowolnytekst” czy print #1,zmienna

2) Z tym trochę więcej kłopotu, choćby z tego powodu, że aplikacje logowania na poczcie są pisane przez właścicieli serwerów pocztowych i u każdego może to  być inne okienko, o innej nazwie, czyli inne na Onecie, inne na wp itd. W związku z tym trudno, a nawet niemożliwe napisanie takiego uniwersalnego programiku dla każdego operatora. Chyba, że znalazło by się jakąś kontrolkę umożliwiającą taką operację, ale nie szukałem i wątpię aby taka była.

Ja korzystam z programu pocztowego i praktycznie nie wchodzę na stronę poczty dla różnych operatorów aby się zalogować i odebrać pocztę bo odbieram w programie pocztowym, gdzie loginy i hasła są wpisane na stałe.

Można samemu napisać taki programik do odbioru poczty także w vb, tylko poco jak są do tego profesjonalne programy.


(Grzeniux) #13

No tak ale jeśli bym chciał pod jedną konkretną stronę, żeby się łączył i wysyłał do przeglądarki z vb6, od czego musiał bym zacząć? Poczte dałem tylko jako przykład równie dobrze mogło to by być nawet korzystanie z wyszukiwarki w google za pomocą vb6.


(floyd) #14

Należało by poznać wiele różnych funkcji API, bibliotek(dll) czy kontrolek(ocx) i umiejętności posługiwania się nimi, jak przykładowo:

Microsoft HTML Object Library (mshtml.dll)

Microsoft Internet controls (shdocvw.dll)

Microsoft Internet transfer Control 6.0(msinet.ocx)

Microsoft mapi controls 6.0 (msmapi32.ocx)

Microsoft Winsock Control 6.0 (mswinsck.ocx)

Bez odpowiedniej literatury trudno jednak nabyć takich umiejętności. W internecie też coś można znaleźć, ale trzeba się naszukać.

Tu przykładowo funkcja uruchamiania dowolnego pliku lub strony z VB6

Option Explicit

Private Declare Function ShellExecute Lib “shell32.dll” Alias “ShellExecuteA” _

(ByVal Hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, _

ByVal lpParameters As String, ByVal lpDirectory As String, _

ByVal nShowCmd As Long) As Long

Private Sub Command1_Click()

Dim i As Integer, adres As String

adres = "http://google.pl"

i = ShellExecute(Hwnd, “Open”, adres, &O0, &O0, -1)

End Sub


(Grzeniux) #15

Chyba jednak sobie daruje wydaje się to być trochę skomplikowane… :)A w jaki sposób można ustawić comboboxa żeby aktualizowała się w nim lista, mam kod który wrzuciłem do timera, lista jest odświeżana ale i również powielana za każdym razem

Dim ff As Long
   Dim line As String
   ff = FreeFile
   Open App.Path & "\combo" For Input As #ff
   Do While Not EOF(ff)
          Line Input #ff, line
        
          If Len(line) Then combo1.AddItem line
   Loop
  Close #ff
end sub

(floyd) #16

Nie wiem czy dobrze zrozumiałem, ale chyba chodzi o to aby nie były dopisywane linie ktore już istnieją.

Option Explicit
Dim ZbiorPomocniczy As String, ZnakKoncaLinii As String
Private Sub Command1_Click()   
 Dim ff As Long
   Dim line As String
   ff = FreeFile: ZnakKoncaLinii = Chr(13) & Chr(10)
   Open App.Path & "\combo.txt" For Input As #ff
   Do While Not EOF(ff)
          Line Input #ff, line
          If InStr(ZbiorPomocniczy, line) = 0 And Len(line) Then
          ZbiorPomocniczy = ZbiorPomocniczy & line & ZnakKoncaLinii
          Combo1.AddItem line
          End If
   Loop
    Close #ff
End Sub

A, tu jeszcze jako ciekawostka: przykład programiku który kiedyś napisałem w VB6

spec0.zip


(Grzeniux) #17

Tak właśnie o to mi chodzi, kodzik który wrzuciłeś już nie dopisuje nowych linii ale duplikuje je, z tym adresem strony coś jest nie tak bo nie może mi go załadować przeglądarka. Jaką literaturę polecasz w tematyce VB6?


(floyd) #18

Nie bardzo wiem co znaczy duplikuje?

Jeżeli wcześnie np. w load był taki plik wczytany to jasne, że będzie je dopisywał.

Trzeba by taki zbiór o nazwie ZbiorPomocniczy utworzyć też w pierwszym wczytaniu, to nie będą potem dopisywane elementy w timer.

Niezbyt jasno przedstawiłeś o co ci chodzi więc musisz sam kombinować.

Link do pliku jest dobry (sprawdziłem), wystarczy tylko kliknąć i powinno dać się ściągnąć (plik mniejszy niż 0,5MB), chyba że ściąganie jest blokowane np. przez antywirus.

Ten programik pokazuje, że w vb6 można też tworzyć bardziej zaawansowane programy.


(Grzeniux) #19

Oki trochę kombinacji i poszło :slight_smile:


(floyd) #20