Excel Forum - Porady, Pomoc,  Excel Help, Excel FAQ Strona Główna
 FAQ  RegulaminRegulamin  Szukaj   Użytkownicy   Grupy   Rejestracja   Profil   Twoje wiadomości   Zaloguj 


Poprzedni temat «» Następny temat
ID tematu: 70593 Skopiuj do schowka Fragment kodu nie wykonuje się w losowych (?) przypadkach.
Autor Wiadomość
wczesny 
Stały bywalec Excelforum


Wersja: Win Office 2016
Pomógł: 34 razy
Posty: 302
Wysłany: 08-04-2021, 14:30   Fragment kodu nie wykonuje się w losowych (?) przypadkach.

Kod:

Function Utworz_tablice_rachunek(podwojnyrachunek As Boolean) 'dodaje to tablicy pozycje z Facon i warunlkami platnosci, zapisuje do arkusza

10        On Error GoTo Utworz_tablice_rachunek_Error
20        Dim wrk As Worksheet: Set wrk = Worksheets("Rachunki_Wplaty")
30        Dim wrk1 As Worksheet: Set wrk1 = Worksheets("Rachunki")
          Dim lrow As Long
          Dim i As Long, j As Long, k As Long, y As Long
          Dim facon As Double, augewicht As Double, terminfacon As Double, autermin As Double, skonto As Double, kursau As Variant
          Dim ary()
          Dim tempary()
          Dim iloscklient As Double
          Dim kwotaF As Double
          Dim kwotaA As Double
          Dim opakowania As Double

40        With Me.lstboxRachunek
         
50            For i = 0 To .ListCount - 1
60                If .Selected(i) Then
                 
70                    ReDim Preserve ary(0 To 18, 0 To j)
                 
80                    ary(0, j) = CLng(Date)
90                    ary(1, j) = Nrrachunku
                     
100                   For k = 2 To 11
110                       ary(k, j) = .List(i, k - 2)
120                   Next
                      'ilosczamowiona = ary(9, j)
130                   iloscklient = ary(11, j)
                      'nrartykulu = ary(8, j)
140                   tempary = Znajdz_cene(ary(9, j), ary(11, j), ary(8, j)) 'call sprawdz cene i reszte warunkow
                     
150                   If podwojnyrachunek Then
160                       facon = tempary(0)
170                       augewicht = 0
180                       terminfacon = tempary(3)
190                       autermin = 0
200                       skonto = tempary(5)
210                       kursau = 0
220                   Else
230                       facon = tempary(0)
240                       augewicht = tempary(1)
250                       terminfacon = tempary(3)
260                       autermin = tempary(4)
270                       skonto = tempary(5)
280                       kursau = Me.txtAu.Value
290                   End If
                     
300                   ary(12, j) = facon 'facon
310                   ary(13, j) = augewicht 'augewicht
                     
320                   If InStr(.List(i, 5), "Au") > 0 Then 'kurs Au
330                       ary(14, j) = kursau
340                   Else
350                       ary(14, j) = 0
360                   End If
                     
370                   ary(15, j) = tempary(6) 'mime galvanik
380                   ary(16, j) = terminfacon 'terminfacon
390                   ary(17, j) = autermin 'autermin
400                   ary(18, j) = skonto 'skonto
                     
410                   kwotaF = kwotaF + Round(iloscklient * facon / 1000 + tempary(6), 2)
420                   kwotaA = kwotaA + Round((iloscklient * augewicht / 1000) * ary(14, j), 2)
                     
430                   j = j + 1
440               End If
450           Next
         
460       End With
         
470       If tempary(7) = "WDT" Then Me.OptWDT = True 'przelacza opcje na WDT
480       If tempary(7) = "RC" Then Me.OptResCharge = True 'przelacza opcje na RC
         
490       With wrk1 'dodaje watrosci do bazy rachunków
500           If Not IsEmpty(.Range("A2").Value) Then
510               .Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)
520           Else
530               .Cells(Rows.Count, "A").End(xlUp).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)
540           End If
550       End With
         
560       With Me.lstboxOpakowania 'koszty opakowan
570           If .ListCount > 0 Then
580               For i = 0 To .ListCount - 1
590                   opakowania = opakowania + (.List(i, 0) * .List(i, 2))
600               Next
610           End If
620       End With
         
630       With wrk 'wplaty
640           If Not IsEmpty(.Range("A2").Value) Then
650               lrow = .Cells(Rows.Count, "A").End(xlUp).Row + 1
660           Else
670               lrow = .Cells(Rows.Count, "A").End(xlUp).Row
680           End If
             
690           .Cells(lrow, 1) = Date
700           .Cells(lrow, 1).NumberFormat = "dd.mm.yyyy"
710           .Cells(lrow, 2) = Nrrachunku
720           .Cells(lrow, 3) = Nazwaklienta
730           .Cells(lrow, 4) = terminfacon
740           .Cells(lrow, 5) = autermin
750           .Cells(lrow, 6) = skonto
760           .Cells(lrow, 7) = kwotaF
770           .Cells(lrow, 8) = kwotaA
780           .Cells(lrow, 9) = opakowania + Val(Replace(Me.txtTransport.Value, ",", "."))
790       End With
         
800       Call Dodaj_nrrachunku_do_listow(ary(2, 0)) 'dodaje numer rachunku w tabeli listow przewozowych


810       Utworz_tablice_rachunek = ary

         
820       On Error GoTo 0
830       Exit Function

Utworz_tablice_rachunek_Error:

840       BLAD = "Error " & Err.Number & " (" & Err.Description & ") in procedure Utworz_tablice_rachunek, line " & Erl & "."
850       Logger "Error", BLAD, Err.Description
860       MsgBox "Wystapil blad."
End Function

Cześć,
mam problem z powyższym kodem tj od 490 do 550 oraz 630 do 790.
Występują przypadki w których tablica oraz dane nie są dodane do arkuszy . Niestety error logger nic nie wykrywa.
Makro jest uruchamiane w "głównym" skoroszycie. W dalszej części kodu otwierany jest inny skoroszyt i te same dane są wklejane. Tam wszystko jest ok.
Jest możliwość, że transpose coś gubi lub użytkownik w czasie wykonywania makra dezaktywuje skoroszyt?
Z góry dzięki za pomysły.
  
ID posta: 403298 Skopiuj do schowka
 
 
Rafał B.
Stały bywalec Excelforum



Wersja: Win Office 2016
Pomógł: 40 razy
Posty: 283
Wysłany: 08-04-2021, 15:42   

Po prostu napisz króciutką funkcję sparwdzającą czy coś tam zostało wklejone (może nawet VBA.Len na pierwszej komórce wystarczy) i dodaj ją tymczasowo do kodu wraz z jakimś przerywnikiem (Msgbox lub Stop) na zasadzie:

Kod:
490       With wrk1 'dodaje watrosci do bazy rachunków
500           If Not IsEmpty(.Range("A2").Value) Then
510               .Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)
520           Else
530               .Cells(Rows.Count, "A").End(xlUp).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)
540           End If
550       End With

' rng np. pierwsza komorka
' moze wystarczy nawet If VBA.Len() = 0
If NothingPasted(rng) Then Stop

(...)


Wtedy na spokojnie w Locals dojdziesz skąd błąd. Transpose gubi powyżej 65k z groszami (słynny wątek Artika na tym forum), wywala błąd przy transpozycji w przypadku zawartości z długimi stringami. Ale w pierwszym przypadku coś jednak wkleiłoby (tylko obcięło dane, a w drugim wywaliło błąd, więc to nie jest najlepszy trop raczej).

PS.
Takie konstrukcje są mało czytelne:
Kod:
.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).Resize((UBound(ary, 2) + 1), (UBound(ary, 1) + 1)) = Application.Transpose(ary)

Rozważyłbym dołożenie tam zmiennych, a nie kilka operacji w jednej linijce, łatwiej też śledzić wartość zmiennych przy debugowaniu; ciężko sobie wyobrazić jak ten Range wygląda
_________________
Jest niemal niemożliwe nauczenie dobrego programowania uczniów, którzy byli narażeni na kontakt z BASIC: jako potencjalni programiści są okaleczeni, bez nadziei na poprawę. (Edsger Dijkstra, pionier informatyki).
Po części dotyczy również VBA.
  
ID posta: 403300 Skopiuj do schowka
 
 
wczesny 
Stały bywalec Excelforum


Wersja: Win Office 2016
Pomógł: 34 razy
Posty: 302
Wysłany: 08-04-2021, 16:04   

Problemem jest, że ten plik używa koleżanka i mam informacje typu "Znowu nie zapisało jednego, ale poprzednie / następne są ok :)", do tego nie zawsze mogę podejść do jej komputera.
Dlatego zastanawiam się w jakich sytuacjach może wystąpić problem.
Dzisiaj to jeszcze raz kilka razy debugowałem i nie mam pojęcia, co może sprawiać problemy.
  
ID posta: 403302 Skopiuj do schowka
 
 
Rafał B.
Stały bywalec Excelforum



Wersja: Win Office 2016
Pomógł: 40 razy
Posty: 283
Wysłany: 08-04-2021, 16:11   

Kod:
 Set wrk = Worksheets("Rachunki_Wplaty")

Czemu brakuje kwalifikacji? Przeoczyłem to na początku, a w przypadku więcej niż jednego skoroszytu jednocześnie to niewybaczalny błąd (koniecznie popraw to w całym kodzie, nie tylko przytoczonym). Sam dobrze zdiagnozowałeś o tej dezaktywacji. Jeśli rezultat ma być w bieżącym "głównym" skoroszycie, to dodaj ThisWorkbook:
Kod:
 Set wrk = ThisWorkbook.Sheets("Rachunki_Wplaty")

Jeśli w tym drugim skoroszycie, to musisz do niego jakiś uchwyt mieć. Możesz iterować po kolekcji Application.Workbooks, użyć GetObject etc.

Ale najbezpieczniej - o ile to możliwe- daj opcję otwierania tego drugiego pliku ze swojego głównego. Wówczas wykluczysz kłopotliwą możliwość innej instancji (chyba, że ograniczamy się do Windows, to API pomoże wylistować wszystkie instancje, w natywnym VBA chyba takiej możliwości nie ma poza "zgadywankami").

PS
W wolnej chwili poczytaj o Model-View-Controller separując warstwę logiki biznesowej od widoku (tutaj userform), bo ten userform zawiera o wiele za dużo logiki niezwiązanej z nim samym. Starasz się pisać ładnie i bardzo dobrze, ale nadal jest tu bałagan. A zastosowanie jakiegoś wzorca projektowego pomoże Ci w przyszłości go uniknąć. Pozdrawiam.
_________________
Jest niemal niemożliwe nauczenie dobrego programowania uczniów, którzy byli narażeni na kontakt z BASIC: jako potencjalni programiści są okaleczeni, bez nadziei na poprawę. (Edsger Dijkstra, pionier informatyki).
Po części dotyczy również VBA.
  
ID posta: 403303 Skopiuj do schowka
 
 
wczesny 
Stały bywalec Excelforum


Wersja: Win Office 2016
Pomógł: 34 razy
Posty: 302
Wysłany: 08-04-2021, 17:19   

Dzięki za rady.

Poprawię kod i zobaczymy czy tylko o to chodziło.

Trochę się dziwię, że nie wywalało błędu.
ID posta: 403304 Skopiuj do schowka
 
 
ąćęłńóś
Excel Expert


Pomógł: 327 razy
Posty: 1615
Wysłany: 08-04-2021, 20:18   

wczesny napisał/a:
Poprawię kod

Powinieneś ...

Pewnie to tylko moje zdanie w "tym temacie", ale jak dla mnie to "funkcja" 'Utworz_tablice_rachunek' wcale nie jest funkcją, przypomina raczej zwykłą podprocedurę 'Sub'.

Z poziomu tej "funkcji" wywołujesz jakieś inne "działania":
Kod:
    tempary = Znajdz_cene(ary(9, j), ary(11, j), ary(8, j)) 'call sprawdz cene i reszte warunkow
    '...
    Call Dodaj_nrrachunku_do_listow(ary(2, 0)) 'dodaje numer rachunku w tabeli listow przewozowych
    '...
    Logger "Error", BLAD, Err.Description
   
    MsgBox "Wystapil blad."

odnoszące się w tle do innych funkcji/"funkcji" i/lub podprocedur, i którą to "funkcję główną" na końcu okraszasz jeszcze taką "egzotyką" jak 'MsgBox' w funkcji ... : / ... co najmniej dziwne ... nie twierdzę, że niedopuszczalne, bo z tego co widzę, to owa "dopuszczalność" ma dla każdego zupełnie inne znaczenie, ale jest to "dziwne" ...

Dodatkowo wykonujesz w funkcji działania "wyjątkowo aktywne", czyli manipulacje na komórkach arkusza - wstawiające określone dane do komórek, które nie są adresatem wyniku funkcji - według mnie (?) ... mojego nastawienia do "instytucji" funkcji jako takiej (?) ... jest to mało "funkcyjne" i wyjątkowo "proceduralne", w sensie wykonywania działań w ramach 'Sub' - podprocedur.
Może jestem "konserwa niereformowalna", ale dla mnie funkcja jest "ciałem" wyjątkowo "biernym", jeśli chodzi o operacje, które wykonuje, jest "obliczeniowa".

Dalej, ogólna klauzula 'On Error GoTo' - jest to wyjątkowe "olanie" tego, co właściwie się wewnątrz tej "funkcji" dzieje i z czym sobie "nie jesteśmy w stanie poradzić" - można by bowiem zadać sobie pytanie, co się właściwie tu dzieje, jeśli z jakimś "błędem" powrócą do kodu "funkcji głównej" owe odwołania do zewnętrznych funkcji/podprocedur, w jakim zakresie, to co zwracają, nie pasuje do oczekiwanego jej działania, wyniku ?
Mamy tu zatem taką sytuację, że funkcja, która w wyniku swojego działania powinna, poprzez swoją "nazwę", zwrócić jakąś "wartość", w przypadku błędu nie zwraca nic, tylko 'MsgBox'.

Tak więc, jak dla mnie - co zaznaczam - przypomina to raczej czekoladowy przekładaniec, niż funkcję wykonującą określone "obliczenia", czy to dla podprocedury, czy to bezpośrednio do komórki(-ek) (UDF).
ID posta: 403314 Skopiuj do schowka
 
 
wczesny 
Stały bywalec Excelforum


Wersja: Win Office 2016
Pomógł: 34 razy
Posty: 302
Wysłany: 08-04-2021, 20:55   

To jest mój pierwszy kontakt z programowaniem, a mam już trochę lat na karku, także jak coś działało, to nie zastanawiałem się za bardzo dlaczego, tylko się z tego cieszyłem :)
Rzeczywiście ten projekt jest chaotyczny ze względu na brak wiedzy oraz planowania przed jego tworzeniem.

Nie wiem za bardzo dlaczego czepiasz się zastosowania funkcji lub procedury. Przecież kod nie wykonuje się inaczej, tylko jest ewentualnie zwracana jakaś wartość.

Obsługa błędów była stworzona do wychwytywania miejsca błędu tj. w pliku tekstowym zapisywana jest nazwa procedury, data, jaki błąd oraz nr linii.
ID posta: 403315 Skopiuj do schowka
 
 
ąćęłńóś
Excel Expert


Pomógł: 327 razy
Posty: 1615
Wysłany: 09-04-2021, 00:29   

To nie kwestia czepiania się ... to moje 3 grosze w temacie, na które nie musisz zwracać uwagi.

Przyjrzyj się temu kodowi uważnie i spróbuj krok po kroku prześledzić go pod kątem:

- dziwnego miejsca występowania argumentu decyzyjnego funkcji (argument 'podwojnyrachunek') - nie "na początku", w miejscu gdzie, wydawałoby się, decydowałby o kierunku przeprowadzanych działań, ale gdzieś w głębi - dlaczego tak jest (?), co o tym decyduje, jaka specyfika działań, że akurat tam, a nie na początku (?),

- sztywności powiązania z 'ListBox'ami:
- - i tego, że sporo "ważnych rzeczy" dzieje się w obrębie tych obiektów, które cały czas trzymają w pamięci jakieś swoje odwołania do niej i jedynie święty Lelum Polelum wie jak to wpływa na działanie innych "konstrukcji", które w międzyczasie coś w tej pamięci grzebią, będąc "wpiętymi" w te odwołania, a jednocześnie będąc odsyłanymi do innych podprocedur/funkcji

- miejsc, w których jest "wybijany z rytmu" jakimiś "przerywnikami":
- - co dzieje się, gdy z jakichś względów, po przesłaniu "działań" do procedur zewnętrznych, powróci on do "głównego nurtu" z "nieakceptowalnymi" wartościami,
- - gdzie obsługa takich niechcianych danych (?)
- - co komukolwiek daje informacja z pliku logu o błędzie ('Err.Description') typu "Object required", itp. (?) i linii jego wystąpienia, skoro i tak nie można odtworzyć sytuacji, która go wywołała ?

- itd.

Według mnie - znowu zaznaczam, według mnie - to nie funkcja tylko podprocedura, poprzeplatana zagnieżdżonymi odwołaniami do kolejnych podprocedur oraz być może funkcji. Takie kolejne zagnieżdżanie nieszczególnie służy prawidłowości wykonywania kodu, chociażby ze względu na "ByRef" i "ByVal" przekazywanych argumentów (jakieś informacje o tym znajdziesz w pomocy podręcznej, jak również na forum).
Według mnie powinieneś porozdzielać to na funkcjonalne etapy, z jednej strony nie objęte "wspólnym ramieniem ListBox'ów" ('lstboxRachunek'), a z drugiej uniezależnione od zagnieżdżeń ('Znajdz_cene' i 'Dodaj_nrrachunku_do_listow'). Konstrukcja "With ... End With", też nie we wszystkich sytuacjach się sprawdzi, czasami (a może nawet) lepsze są przypisania 'Set'.

Jak to zrobić, porozdzielać ? Nie wiem, sam twój kod nie daje ogólnego wglądu w proces i kolejność w jakiej się to ma odbywać - brak przykładu, choćby z grubsza symulującego prawdziwe zagadnienie.

Ps: Wszystko dzieje się w obrębie formatki 'UserForm', a więc dochodzą tu również jej obciążenia-uwarunkowania, wynikające chociażby z kolejności obsługiwanych w niej zdarzeń, robi się z tego cały łańcuszek - łatwo to sprawdzić tworząc formatkę testową z jakimś obiektem i jego obsługiwanymi zdarzeniami, można wtedy na własnej skórze przekonać się jak taka formatka "hałasuje" okropnie, skacząc po wielokroć po tych samych zdarzeniach w danym obiekcie - to też trzeba uwzględnić.
ID posta: 403323 Skopiuj do schowka
 
 
wczesny 
Stały bywalec Excelforum


Wersja: Win Office 2016
Pomógł: 34 razy
Posty: 302
Wysłany: 09-04-2021, 09:03   

Postaram się usunąć dane wrażliwe i załączę cały plik.

Generalnie jeżeli chodzi o poprawność danych, to wszystko jest sprawdzane w podprocedurach procedury głównej, czyli jeżeli coś nie zgadza kod, nie ma prawa dojść do tego momentu.
ID posta: 403327 Skopiuj do schowka
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Dodaj temat do Ulubionych
Wersja do druku

Skocz do:  

Powered by phpBB modified by Przemo © 2003 phpBB Group
Theme xandgreen created by spleen& Programosy modified v0.3 by warna
Opieka techniczna www.marketingNET.pl

Archiwum

Strona używa plików cookies.

Kliknij tutaj, żeby dowiedzieć się jaki jest cel używania cookies oraz jak zmienić ustawienia cookie w przeglądarce.
Korzystając ze strony użytkownik wyraża zgodę na używanie plików cookies, zgodnie z bieżącymi ustawieniami przeglądarki.
Sprawdź, w jaki sposób przetwarzamy dane osobowe